Showing preview only (2,596K chars total). Download the full file or copy to clipboard to get everything.
Repository: demilich1/metastone
Branch: master
Commit: bab2c6a14370
Files: 2009
Total size: 2.0 MB
Directory structure:
gitextract_a_mhvwr6/
├── .gitignore
├── LICENSE
├── README.md
├── app/
│ ├── build.fxbuild
│ ├── build.gradle
│ ├── javafx.plugin
│ ├── lib/
│ │ ├── controlsfx-8.40.10-20151003.010657-492.jar
│ │ └── nitty-gritty-mvc.jar
│ ├── manifest.json
│ └── src/
│ ├── deploy/
│ │ └── package/
│ │ └── windows/
│ │ └── Metastone.iss
│ └── main/
│ ├── java/
│ │ └── net/
│ │ └── demilich/
│ │ └── metastone/
│ │ ├── ApplicationFacade.java
│ │ ├── ApplicationStartupCommand.java
│ │ ├── DevCardTools.java
│ │ ├── MetaStone.java
│ │ ├── PlayGameCommand.java
│ │ ├── gui/
│ │ │ ├── DigitFactory.java
│ │ │ ├── DigitTemplate.java
│ │ │ ├── IconFactory.java
│ │ │ ├── autoupdate/
│ │ │ │ ├── AutoUpdateMediator.java
│ │ │ │ └── CheckForUpdateCommand.java
│ │ │ ├── battleofdecks/
│ │ │ │ ├── BattleBatchResult.java
│ │ │ │ ├── BattleBatchResultToken.java
│ │ │ │ ├── BattleConfig.java
│ │ │ │ ├── BattleDeckResult.java
│ │ │ │ ├── BattleOfDecksConfigView.java
│ │ │ │ ├── BattleOfDecksMediator.java
│ │ │ │ ├── BattleOfDecksResultView.java
│ │ │ │ ├── BattleResult.java
│ │ │ │ └── StartBattleOfDecksCommand.java
│ │ │ ├── cards/
│ │ │ │ ├── CardProxy.java
│ │ │ │ ├── CardToken.java
│ │ │ │ ├── CardTokenFactory.java
│ │ │ │ ├── CardTooltip.java
│ │ │ │ └── HandCard.java
│ │ │ ├── common/
│ │ │ │ ├── BehaviourStringConverter.java
│ │ │ │ ├── CardSetStringConverter.java
│ │ │ │ ├── ComboBoxKeyHandler.java
│ │ │ │ ├── DeckFormatStringConverter.java
│ │ │ │ ├── DeckStringConverter.java
│ │ │ │ ├── HeroStringConverter.java
│ │ │ │ ├── IntegerTextField.java
│ │ │ │ └── RestrictedTextField.java
│ │ │ ├── deckbuilder/
│ │ │ │ ├── AddCardToDeckCommand.java
│ │ │ │ ├── CardEntry.java
│ │ │ │ ├── CardEntryFactory.java
│ │ │ │ ├── CardFilter.java
│ │ │ │ ├── CardFilterView.java
│ │ │ │ ├── CardListView.java
│ │ │ │ ├── CardView.java
│ │ │ │ ├── ChangeDeckNameCommand.java
│ │ │ │ ├── ChooseClassView.java
│ │ │ │ ├── DeckBuilderMediator.java
│ │ │ │ ├── DeckBuilderView.java
│ │ │ │ ├── DeckEntry.java
│ │ │ │ ├── DeckFormatProxy.java
│ │ │ │ ├── DeckInfoView.java
│ │ │ │ ├── DeckListView.java
│ │ │ │ ├── DeckNameView.java
│ │ │ │ ├── DeckProxy.java
│ │ │ │ ├── DeleteDeckCommand.java
│ │ │ │ ├── FillDeckWithRandomCardsCommand.java
│ │ │ │ ├── FilterCardsCommand.java
│ │ │ │ ├── ImportDeckCommand.java
│ │ │ │ ├── LoadDeckFormatsCommand.java
│ │ │ │ ├── LoadDecksCommand.java
│ │ │ │ ├── RemoveCardFromDeckCommand.java
│ │ │ │ ├── SaveDeckCommand.java
│ │ │ │ ├── SetActiveDeckCommand.java
│ │ │ │ ├── importer/
│ │ │ │ │ ├── HearthHeadImporter.java
│ │ │ │ │ ├── HearthPwnImporter.java
│ │ │ │ │ ├── IDeckImporter.java
│ │ │ │ │ ├── IcyVeinsImporter.java
│ │ │ │ │ ├── ImporterFactory.java
│ │ │ │ │ └── TempostormImporter.java
│ │ │ │ └── metadeck/
│ │ │ │ ├── AddDeckToMetaDeckCommand.java
│ │ │ │ ├── MetaDeckListView.java
│ │ │ │ ├── MetaDeckView.java
│ │ │ │ └── RemoveDeckFromMetaDeckCommand.java
│ │ │ ├── dialog/
│ │ │ │ ├── DialogMediator.java
│ │ │ │ ├── DialogNotification.java
│ │ │ │ ├── DialogResult.java
│ │ │ │ ├── DialogType.java
│ │ │ │ ├── IDialogListener.java
│ │ │ │ ├── ModalDialog.java
│ │ │ │ └── UserDialog.java
│ │ │ ├── gameconfig/
│ │ │ │ └── PlayerConfigView.java
│ │ │ ├── main/
│ │ │ │ └── ApplicationMediator.java
│ │ │ ├── mainmenu/
│ │ │ │ ├── MainMenuMediator.java
│ │ │ │ └── MainMenuView.java
│ │ │ ├── playmode/
│ │ │ │ ├── GameBoardView.java
│ │ │ │ ├── GameContextVisualizable.java
│ │ │ │ ├── GameToken.java
│ │ │ │ ├── HeroToken.java
│ │ │ │ ├── HumanActionPromptView.java
│ │ │ │ ├── HumanMulliganView.java
│ │ │ │ ├── LoadingBoardView.java
│ │ │ │ ├── PlayModeMediator.java
│ │ │ │ ├── PlayModeView.java
│ │ │ │ ├── StartGameCommand.java
│ │ │ │ ├── SummonToken.java
│ │ │ │ ├── animation/
│ │ │ │ │ ├── AnimationCompletedCommand.java
│ │ │ │ │ ├── AnimationLockCommand.java
│ │ │ │ │ ├── AnimationProxy.java
│ │ │ │ │ ├── AnimationStartedCommand.java
│ │ │ │ │ ├── CardPlayedToken.java
│ │ │ │ │ ├── CardRevealedToken.java
│ │ │ │ │ ├── DamageEventVisualizer.java
│ │ │ │ │ ├── DamageNumber.java
│ │ │ │ │ ├── EventVisualizerDispatcher.java
│ │ │ │ │ ├── HealEventVisualizer.java
│ │ │ │ │ ├── HealingNumber.java
│ │ │ │ │ ├── IAnimationListener.java
│ │ │ │ │ ├── IGameEventVisualizer.java
│ │ │ │ │ ├── JoustToken.java
│ │ │ │ │ ├── JoustVisualizer.java
│ │ │ │ │ ├── PlayCardVisualizer.java
│ │ │ │ │ └── RevealCardVisualizer.java
│ │ │ │ └── config/
│ │ │ │ ├── PlayModeConfigMediator.java
│ │ │ │ ├── PlayModeConfigView.java
│ │ │ │ ├── PlayerConfigType.java
│ │ │ │ ├── RequestDeckFormatsCommand.java
│ │ │ │ └── RequestDecksCommand.java
│ │ │ ├── sandboxmode/
│ │ │ │ ├── CardCollectionEditor.java
│ │ │ │ ├── CardPanel.java
│ │ │ │ ├── EntityEditor.java
│ │ │ │ ├── GameTagEntry.java
│ │ │ │ ├── ICardCollectionEditingListener.java
│ │ │ │ ├── MinionPanel.java
│ │ │ │ ├── PlayerPanel.java
│ │ │ │ ├── SandboxEditor.java
│ │ │ │ ├── SandboxModeConfigView.java
│ │ │ │ ├── SandboxModeMediator.java
│ │ │ │ ├── SandboxModeView.java
│ │ │ │ ├── SandboxProxy.java
│ │ │ │ ├── ToolboxView.java
│ │ │ │ ├── actions/
│ │ │ │ │ ├── EditEntityAction.java
│ │ │ │ │ ├── KillAction.java
│ │ │ │ │ ├── SetManaAction.java
│ │ │ │ │ ├── SetMaxManaAction.java
│ │ │ │ │ └── SilenceAction.java
│ │ │ │ └── commands/
│ │ │ │ ├── CreateNewSandboxCommand.java
│ │ │ │ ├── ModifyPlayerDeckCommand.java
│ │ │ │ ├── ModifyPlayerHandCommand.java
│ │ │ │ ├── PerformActionCommand.java
│ │ │ │ ├── SelectPlayerCommand.java
│ │ │ │ ├── SpawnMinionCommand.java
│ │ │ │ ├── StartPlaySandboxCommand.java
│ │ │ │ └── StopPlaySandboxCommand.java
│ │ │ ├── simulationmode/
│ │ │ │ ├── PlayerConfigView.java
│ │ │ │ ├── PlayerInfoView.java
│ │ │ │ ├── SimulateGamesCommand.java
│ │ │ │ ├── SimulationMediator.java
│ │ │ │ ├── SimulationModeConfigView.java
│ │ │ │ ├── SimulationResult.java
│ │ │ │ ├── SimulationResultView.java
│ │ │ │ ├── StatEntry.java
│ │ │ │ └── WaitForSimulationView.java
│ │ │ └── trainingmode/
│ │ │ ├── PerformTrainingCommand.java
│ │ │ ├── RequestTrainingDataCommand.java
│ │ │ ├── SaveTrainingDataCommand.java
│ │ │ ├── TrainingConfig.java
│ │ │ ├── TrainingConfigView.java
│ │ │ ├── TrainingModeMediator.java
│ │ │ ├── TrainingModeView.java
│ │ │ ├── TrainingProgressReport.java
│ │ │ └── TrainingProxy.java
│ │ └── tools/
│ │ ├── CardCreator.java
│ │ ├── CardEditor.java
│ │ ├── EditorMainWindow.java
│ │ ├── ICardEditor.java
│ │ ├── ITextFieldAction.java
│ │ ├── IntegerListener.java
│ │ ├── MinionCardPanel.java
│ │ ├── SpellCardPanel.java
│ │ ├── SpellDescSerializer.java
│ │ ├── SpellStringConverter.java
│ │ └── WeaponClassPanel.java
│ └── resources/
│ ├── css/
│ │ ├── deckbuilder.css
│ │ ├── gameboard.css
│ │ ├── main.css
│ │ └── mainmenu.css
│ ├── fxml/
│ │ ├── BattleBatchResultToken.fxml
│ │ ├── BattleOfDecksConfigView.fxml
│ │ ├── BattleOfDecksResultView.fxml
│ │ ├── CardCollectionEditor.fxml
│ │ ├── CardEntry.fxml
│ │ ├── CardFilterView.fxml
│ │ ├── CardPanel.fxml
│ │ ├── CardTooltip.fxml
│ │ ├── CardView.fxml
│ │ ├── ChooseClassView.fxml
│ │ ├── DeckBuilderView.fxml
│ │ ├── DeckEntry.fxml
│ │ ├── DeckInfoView.fxml
│ │ ├── DeckListView.fxml
│ │ ├── DeckNameView.fxml
│ │ ├── DigitTemplate.fxml
│ │ ├── EditorMainWindow.fxml
│ │ ├── EntityEditor.fxml
│ │ ├── GameBoardView.fxml
│ │ ├── HandCard.fxml
│ │ ├── HeroToken.fxml
│ │ ├── HumanMulliganView.fxml
│ │ ├── LoadingBoardView.fxml
│ │ ├── MainMenuView.fxml
│ │ ├── MetaDeckListView.fxml
│ │ ├── MetaDeckView (2).fxml
│ │ ├── MetaDeckView.fxml
│ │ ├── MinionCardPanel.fxml
│ │ ├── MinionPanel.fxml
│ │ ├── PlayModeConfigView.fxml
│ │ ├── PlayModeView.fxml
│ │ ├── PlayerConfigView.fxml
│ │ ├── PlayerInfoView.fxml
│ │ ├── PlayerPanel.fxml
│ │ ├── SandboxModeConfigView.fxml
│ │ ├── SandboxModeView.fxml
│ │ ├── SimulationModeConfigView.fxml
│ │ ├── SimulationResultView.fxml
│ │ ├── SpellCardPanel.fxml
│ │ ├── SummonToken.fxml
│ │ ├── ToolboxView.fxml
│ │ ├── TrainingConfigView.fxml
│ │ ├── TrainingModeView.fxml
│ │ ├── UserDialog.fxml
│ │ └── WaitForSimulationView.fxml
│ └── logback.xml
├── build.gradle
├── cards/
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ └── resources/
│ │ ├── cards/
│ │ │ ├── basic/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── hero_malfurion.json
│ │ │ │ │ ├── hero_power_shapeshift.json
│ │ │ │ │ ├── minion_ironbark_protector.json
│ │ │ │ │ ├── spell_claw.json
│ │ │ │ │ ├── spell_excess_mana.json
│ │ │ │ │ ├── spell_healing_touch.json
│ │ │ │ │ ├── spell_innervate.json
│ │ │ │ │ ├── spell_mark_of_the_wild.json
│ │ │ │ │ ├── spell_moonfire.json
│ │ │ │ │ ├── spell_savage_roar.json
│ │ │ │ │ ├── spell_starfire.json
│ │ │ │ │ ├── spell_swipe.json
│ │ │ │ │ └── spell_wild_growth.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── hero_power_steady_shot.json
│ │ │ │ │ ├── hero_rexxar.json
│ │ │ │ │ ├── minion_houndmaster.json
│ │ │ │ │ ├── minion_starving_buzzard.json
│ │ │ │ │ ├── minion_timber_wolf.json
│ │ │ │ │ ├── minion_tundra_rhino.json
│ │ │ │ │ ├── spell_animal_companion.json
│ │ │ │ │ ├── spell_arcane_shot.json
│ │ │ │ │ ├── spell_hunters_mark.json
│ │ │ │ │ ├── spell_kill_command.json
│ │ │ │ │ ├── spell_multi-shot.json
│ │ │ │ │ ├── spell_tracking.json
│ │ │ │ │ ├── token_huffer.json
│ │ │ │ │ ├── token_leokk.json
│ │ │ │ │ └── token_misha.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── hero_jaina.json
│ │ │ │ │ ├── hero_power_fireblast.json
│ │ │ │ │ ├── minion_water_elemental.json
│ │ │ │ │ ├── spell_arcane_explosion.json
│ │ │ │ │ ├── spell_arcane_intellect.json
│ │ │ │ │ ├── spell_arcane_missiles.json
│ │ │ │ │ ├── spell_fireball.json
│ │ │ │ │ ├── spell_flamestrike.json
│ │ │ │ │ ├── spell_frost_nova.json
│ │ │ │ │ ├── spell_frostbolt.json
│ │ │ │ │ ├── spell_mirror_image.json
│ │ │ │ │ ├── spell_polymorph.json
│ │ │ │ │ ├── token_mirror_image.json
│ │ │ │ │ └── token_sheep.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_acidic_swamp_ooze.json
│ │ │ │ │ ├── minion_archmage.json
│ │ │ │ │ ├── minion_bloodfen_raptor.json
│ │ │ │ │ ├── minion_bluegill_warrior.json
│ │ │ │ │ ├── minion_booty_bay_bodyguard.json
│ │ │ │ │ ├── minion_boulderfist_ogre.json
│ │ │ │ │ ├── minion_chillwind_yeti.json
│ │ │ │ │ ├── minion_core_hound.json
│ │ │ │ │ ├── minion_dalaran_mage.json
│ │ │ │ │ ├── minion_darkscale_healer.json
│ │ │ │ │ ├── minion_dragonling_mechanic.json
│ │ │ │ │ ├── minion_elven_archer.json
│ │ │ │ │ ├── minion_frostwolf_grunt.json
│ │ │ │ │ ├── minion_frostwolf_warlord.json
│ │ │ │ │ ├── minion_gnomish_inventor.json
│ │ │ │ │ ├── minion_goldshire_footman.json
│ │ │ │ │ ├── minion_grimscale_oracle.json
│ │ │ │ │ ├── minion_gurubashi_berserker.json
│ │ │ │ │ ├── minion_ironforge_rifleman.json
│ │ │ │ │ ├── minion_ironfur_grizzly.json
│ │ │ │ │ ├── minion_kobold_geomancer.json
│ │ │ │ │ ├── minion_lord_of_the_arena.json
│ │ │ │ │ ├── minion_magma_rager.json
│ │ │ │ │ ├── minion_murloc_raider.json
│ │ │ │ │ ├── minion_murloc_tidehunter.json
│ │ │ │ │ ├── minion_nightblade.json
│ │ │ │ │ ├── minion_novice_engineer.json
│ │ │ │ │ ├── minion_oasis_snapjaw.json
│ │ │ │ │ ├── minion_ogre_magi.json
│ │ │ │ │ ├── minion_raid_leader.json
│ │ │ │ │ ├── minion_razorfen_hunter.json
│ │ │ │ │ ├── minion_reckless_rocketeer.json
│ │ │ │ │ ├── minion_river_crocolisk.json
│ │ │ │ │ ├── minion_senjin_shieldmasta.json
│ │ │ │ │ ├── minion_shattered_sun_cleric.json
│ │ │ │ │ ├── minion_silverback_patriarch.json
│ │ │ │ │ ├── minion_stonetusk_boar.json
│ │ │ │ │ ├── minion_stormpike_commando.json
│ │ │ │ │ ├── minion_stormwind_champion.json
│ │ │ │ │ ├── minion_stormwind_knight.json
│ │ │ │ │ ├── minion_voodoo_doctor.json
│ │ │ │ │ ├── minion_war_golem.json
│ │ │ │ │ ├── minion_wolfrider.json
│ │ │ │ │ ├── spell_the_coin.json
│ │ │ │ │ ├── token_boar.json
│ │ │ │ │ ├── token_mechanical_dragonling.json
│ │ │ │ │ └── token_murloc_scout.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── hero_power_reinforce.json
│ │ │ │ │ ├── hero_uther.json
│ │ │ │ │ ├── minion_guardian_of_kings.json
│ │ │ │ │ ├── spell_blessing_of_kings.json
│ │ │ │ │ ├── spell_blessing_of_might.json
│ │ │ │ │ ├── spell_consecration.json
│ │ │ │ │ ├── spell_hammer_of_wrath.json
│ │ │ │ │ ├── spell_hand_of_protection.json
│ │ │ │ │ ├── spell_holy_light.json
│ │ │ │ │ ├── spell_humility.json
│ │ │ │ │ ├── token_silver_hand_recruit.json
│ │ │ │ │ ├── weapon_lights_justice.json
│ │ │ │ │ └── weapon_truesilver_champion.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── hero_anduin.json
│ │ │ │ │ ├── hero_power_lesser_heal.json
│ │ │ │ │ ├── minion_northshire_cleric.json
│ │ │ │ │ ├── spell_divine_spirit.json
│ │ │ │ │ ├── spell_holy_nova.json
│ │ │ │ │ ├── spell_holy_smite.json
│ │ │ │ │ ├── spell_mind_blast.json
│ │ │ │ │ ├── spell_mind_control.json
│ │ │ │ │ ├── spell_mind_vision.json
│ │ │ │ │ ├── spell_power_word_shield.json
│ │ │ │ │ ├── spell_shadow_word_death.json
│ │ │ │ │ └── spell_shadow_word_pain.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── hero_power_dagger_mastery.json
│ │ │ │ │ ├── hero_valeera.json
│ │ │ │ │ ├── spell_assassinate.json
│ │ │ │ │ ├── spell_backstab.json
│ │ │ │ │ ├── spell_deadly_poison.json
│ │ │ │ │ ├── spell_fan_of_knives.json
│ │ │ │ │ ├── spell_sap.json
│ │ │ │ │ ├── spell_shiv.json
│ │ │ │ │ ├── spell_sinister_strike.json
│ │ │ │ │ ├── spell_sprint.json
│ │ │ │ │ ├── spell_vanish.json
│ │ │ │ │ ├── weapon_assassins_blade.json
│ │ │ │ │ └── weapon_wicked_knife.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── hero_power_totemic_call.json
│ │ │ │ │ ├── hero_thrall.json
│ │ │ │ │ ├── minion_fire_elemental.json
│ │ │ │ │ ├── minion_flametongue_totem.json
│ │ │ │ │ ├── minion_windspeaker.json
│ │ │ │ │ ├── spell_ancestral_healing.json
│ │ │ │ │ ├── spell_bloodlust.json
│ │ │ │ │ ├── spell_frost_shock.json
│ │ │ │ │ ├── spell_hex.json
│ │ │ │ │ ├── spell_rockbiter_weapon.json
│ │ │ │ │ ├── spell_totemic_might.json
│ │ │ │ │ ├── spell_windfury.json
│ │ │ │ │ ├── token_frog.json
│ │ │ │ │ ├── token_healing_totem.json
│ │ │ │ │ ├── token_searing_totem.json
│ │ │ │ │ ├── token_stoneclaw_totem.json
│ │ │ │ │ └── token_wrath_of_air_totem.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── hero_guldan.json
│ │ │ │ │ ├── hero_power_life_tap.json
│ │ │ │ │ ├── minion_dread_infernal.json
│ │ │ │ │ ├── minion_succubus.json
│ │ │ │ │ ├── minion_voidwalker.json
│ │ │ │ │ ├── spell_corruption.json
│ │ │ │ │ ├── spell_drain_life.json
│ │ │ │ │ ├── spell_hellfire.json
│ │ │ │ │ ├── spell_mortal_coil.json
│ │ │ │ │ ├── spell_sacrificial_pact.json
│ │ │ │ │ ├── spell_shadow_bolt.json
│ │ │ │ │ └── spell_soulfire.json
│ │ │ │ └── warrior/
│ │ │ │ ├── hero_garrosh.json
│ │ │ │ ├── hero_power_armor_up.json
│ │ │ │ ├── minion_korkron_elite.json
│ │ │ │ ├── minion_warsong_commander.json
│ │ │ │ ├── spell_charge.json
│ │ │ │ ├── spell_cleave.json
│ │ │ │ ├── spell_execute.json
│ │ │ │ ├── spell_heroic_strike.json
│ │ │ │ ├── spell_shield_block.json
│ │ │ │ ├── spell_whirlwind.json
│ │ │ │ ├── weapon_arcanite_reaper.json
│ │ │ │ └── weapon_fiery_war_axe.json
│ │ │ ├── blackrock_mountain/
│ │ │ │ ├── hero_power_die_insect.json
│ │ │ │ ├── hero_ragnaros.json
│ │ │ │ ├── minion_axe_flinger.json
│ │ │ │ ├── minion_blackwing_corruptor.json
│ │ │ │ ├── minion_blackwing_technician.json
│ │ │ │ ├── minion_chromaggus.json
│ │ │ │ ├── minion_core_rager.json
│ │ │ │ ├── minion_dark_iron_skulker.json
│ │ │ │ ├── minion_dragon_consort.json
│ │ │ │ ├── minion_dragon_egg.json
│ │ │ │ ├── minion_dragonkin_sorcerer.json
│ │ │ │ ├── minion_drakonid_crusher.json
│ │ │ │ ├── minion_druid_of_the_flame.json
│ │ │ │ ├── minion_emperor_thaurissan.json
│ │ │ │ ├── minion_fireguard_destroyer.json
│ │ │ │ ├── minion_flamewaker.json
│ │ │ │ ├── minion_grim_patron.json
│ │ │ │ ├── minion_hungry_dragon.json
│ │ │ │ ├── minion_imp_gang_boss.json
│ │ │ │ ├── minion_majordomo_executus.json
│ │ │ │ ├── minion_nefarian.json
│ │ │ │ ├── minion_rend_blackhand.json
│ │ │ │ ├── minion_twilight_whelp.json
│ │ │ │ ├── minion_volcanic_drake.json
│ │ │ │ ├── minion_volcanic_lumberer.json
│ │ │ │ ├── spell_demonwrath.json
│ │ │ │ ├── spell_dragons_breath.json
│ │ │ │ ├── spell_gang_up.json
│ │ │ │ ├── spell_lava_shock.json
│ │ │ │ ├── spell_quick_shot.json
│ │ │ │ ├── spell_resurrect.json
│ │ │ │ ├── spell_revenge.json
│ │ │ │ ├── spell_solemn_vigil.json
│ │ │ │ ├── spell_tail_swipe.json
│ │ │ │ ├── token_black_whelp.json
│ │ │ │ ├── token_flame_bird_form.json
│ │ │ │ ├── token_flame_lion_form.json
│ │ │ │ └── token_flame_lionbird_form.json
│ │ │ ├── classic/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── minion_ancient_of_lore.json
│ │ │ │ │ ├── minion_ancient_of_war.json
│ │ │ │ │ ├── minion_cenarius.json
│ │ │ │ │ ├── minion_druid_of_the_claw.json
│ │ │ │ │ ├── minion_keeper_of_the_grove.json
│ │ │ │ │ ├── spell_bite.json
│ │ │ │ │ ├── spell_force_of_nature.json
│ │ │ │ │ ├── spell_mark_of_nature.json
│ │ │ │ │ ├── spell_mark_of_nature_1.json
│ │ │ │ │ ├── spell_mark_of_nature_2.json
│ │ │ │ │ ├── spell_mark_of_nature_3.json
│ │ │ │ │ ├── spell_naturalize.json
│ │ │ │ │ ├── spell_nourish.json
│ │ │ │ │ ├── spell_nourish_1.json
│ │ │ │ │ ├── spell_nourish_2.json
│ │ │ │ │ ├── spell_nourish_3.json
│ │ │ │ │ ├── spell_power_of_the_wild.json
│ │ │ │ │ ├── spell_power_of_the_wild_1.json
│ │ │ │ │ ├── spell_power_of_the_wild_2.json
│ │ │ │ │ ├── spell_power_of_the_wild_3.json
│ │ │ │ │ ├── spell_savagery.json
│ │ │ │ │ ├── spell_soul_of_the_forest.json
│ │ │ │ │ ├── spell_starfall.json
│ │ │ │ │ ├── spell_starfall_1.json
│ │ │ │ │ ├── spell_starfall_2.json
│ │ │ │ │ ├── spell_starfall_3.json
│ │ │ │ │ ├── spell_wrath.json
│ │ │ │ │ ├── spell_wrath_1.json
│ │ │ │ │ ├── spell_wrath_2.json
│ │ │ │ │ ├── spell_wrath_3.json
│ │ │ │ │ ├── token_bear_form.json
│ │ │ │ │ ├── token_cat_form.json
│ │ │ │ │ ├── token_catbear_form.json
│ │ │ │ │ ├── token_panther.json
│ │ │ │ │ ├── token_treant.json
│ │ │ │ │ └── token_treant_taunt.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── minion_king_krush.json
│ │ │ │ │ ├── minion_savannah_highmane.json
│ │ │ │ │ ├── minion_scavenging_hyena.json
│ │ │ │ │ ├── secret_explosive_trap.json
│ │ │ │ │ ├── secret_freezing_trap.json
│ │ │ │ │ ├── secret_misdirection.json
│ │ │ │ │ ├── secret_snake_trap.json
│ │ │ │ │ ├── secret_snipe.json
│ │ │ │ │ ├── spell_bestial_wrath.json
│ │ │ │ │ ├── spell_deadly_shot.json
│ │ │ │ │ ├── spell_explosive_shot.json
│ │ │ │ │ ├── spell_flare.json
│ │ │ │ │ ├── spell_unleash_the_hounds.json
│ │ │ │ │ ├── token_hound.json
│ │ │ │ │ ├── token_hyena.json
│ │ │ │ │ ├── token_snake.json
│ │ │ │ │ ├── weapon_eaglehorn_bow.json
│ │ │ │ │ └── weapon_gladiators_longbow.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── minion_archmage_antonidas.json
│ │ │ │ │ ├── minion_ethereal_arcanist.json
│ │ │ │ │ ├── minion_kirin_tor_mage.json
│ │ │ │ │ ├── minion_mana_wyrm.json
│ │ │ │ │ ├── minion_sorcerers_apprentice.json
│ │ │ │ │ ├── secret_counterspell.json
│ │ │ │ │ ├── secret_ice_barrier.json
│ │ │ │ │ ├── secret_ice_block.json
│ │ │ │ │ ├── secret_mirror_entity.json
│ │ │ │ │ ├── secret_spellbender.json
│ │ │ │ │ ├── secret_vaporize.json
│ │ │ │ │ ├── spell_blizzard.json
│ │ │ │ │ ├── spell_cone_of_cold.json
│ │ │ │ │ ├── spell_pyroblast.json
│ │ │ │ │ └── token_spellbender.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_abomination.json
│ │ │ │ │ ├── minion_abusive_sergeant.json
│ │ │ │ │ ├── minion_acolyte_of_pain.json
│ │ │ │ │ ├── minion_alarm-o-bot.json
│ │ │ │ │ ├── minion_alexstrasza.json
│ │ │ │ │ ├── minion_amani_berserker.json
│ │ │ │ │ ├── minion_ancient_brewmaster.json
│ │ │ │ │ ├── minion_ancient_mage.json
│ │ │ │ │ ├── minion_ancient_watcher.json
│ │ │ │ │ ├── minion_angry_chicken.json
│ │ │ │ │ ├── minion_arcane_golem.json
│ │ │ │ │ ├── minion_argent_commander.json
│ │ │ │ │ ├── minion_argent_squire.json
│ │ │ │ │ ├── minion_baron_geddon.json
│ │ │ │ │ ├── minion_big_game_hunter.json
│ │ │ │ │ ├── minion_blood_knight.json
│ │ │ │ │ ├── minion_bloodmage_thalnos.json
│ │ │ │ │ ├── minion_bloodsail_corsair.json
│ │ │ │ │ ├── minion_bloodsail_raider.json
│ │ │ │ │ ├── minion_cairne_bloodhoof.json
│ │ │ │ │ ├── minion_captain_greenskin.json
│ │ │ │ │ ├── minion_coldlight_oracle.json
│ │ │ │ │ ├── minion_coldlight_seer.json
│ │ │ │ │ ├── minion_crazed_alchemist.json
│ │ │ │ │ ├── minion_cult_master.json
│ │ │ │ │ ├── minion_dark_iron_dwarf.json
│ │ │ │ │ ├── minion_deathwing.json
│ │ │ │ │ ├── minion_defender_of_argus.json
│ │ │ │ │ ├── minion_demolisher.json
│ │ │ │ │ ├── minion_dire_wolf_alpha.json
│ │ │ │ │ ├── minion_doomsayer.json
│ │ │ │ │ ├── minion_dread_corsair.json
│ │ │ │ │ ├── minion_earthen_ring_farseer.json
│ │ │ │ │ ├── minion_emperor_cobra.json
│ │ │ │ │ ├── minion_faceless_manipulator.json
│ │ │ │ │ ├── minion_faerie_dragon.json
│ │ │ │ │ ├── minion_fen_creeper.json
│ │ │ │ │ ├── minion_flesheating_ghoul.json
│ │ │ │ │ ├── minion_frost_elemental.json
│ │ │ │ │ ├── minion_gadgetzan_auctioneer.json
│ │ │ │ │ ├── minion_gruul.json
│ │ │ │ │ ├── minion_harrison_jones.json
│ │ │ │ │ ├── minion_harvest_golem.json
│ │ │ │ │ ├── minion_hogger.json
│ │ │ │ │ ├── minion_hungry_crab.json
│ │ │ │ │ ├── minion_illidan_stormrage.json
│ │ │ │ │ ├── minion_imp_master.json
│ │ │ │ │ ├── minion_injured_blademaster.json
│ │ │ │ │ ├── minion_ironbeak_owl.json
│ │ │ │ │ ├── minion_jungle_panther.json
│ │ │ │ │ ├── minion_king_mukla.json
│ │ │ │ │ ├── minion_knife_juggler.json
│ │ │ │ │ ├── minion_leeroy_jenkins.json
│ │ │ │ │ ├── minion_leper_gnome.json
│ │ │ │ │ ├── minion_lightwarden.json
│ │ │ │ │ ├── minion_loot_hoarder.json
│ │ │ │ │ ├── minion_lorewalker_cho.json
│ │ │ │ │ ├── minion_mad_bomber.json
│ │ │ │ │ ├── minion_malygos.json
│ │ │ │ │ ├── minion_mana_addict.json
│ │ │ │ │ ├── minion_mana_wraith.json
│ │ │ │ │ ├── minion_master_swordsmith.json
│ │ │ │ │ ├── minion_millhouse_manastorm.json
│ │ │ │ │ ├── minion_mind_control_tech.json
│ │ │ │ │ ├── minion_mogushan_warden.json
│ │ │ │ │ ├── minion_molten_giant.json
│ │ │ │ │ ├── minion_mountain_giant.json
│ │ │ │ │ ├── minion_murloc_tidecaller.json
│ │ │ │ │ ├── minion_murloc_warleader.json
│ │ │ │ │ ├── minion_nat_pagle.json
│ │ │ │ │ ├── minion_nozdormu.json
│ │ │ │ │ ├── minion_onyxia.json
│ │ │ │ │ ├── minion_pint-sized_summoner.json
│ │ │ │ │ ├── minion_priestess_of_elune.json
│ │ │ │ │ ├── minion_questing_adventurer.json
│ │ │ │ │ ├── minion_raging_worgen.json
│ │ │ │ │ ├── minion_ravenholdt_assassin.json
│ │ │ │ │ ├── minion_scarlet_crusader.json
│ │ │ │ │ ├── minion_sea_giant.json
│ │ │ │ │ ├── minion_secretkeeper.json
│ │ │ │ │ ├── minion_shieldbearer.json
│ │ │ │ │ ├── minion_silver_hand_knight.json
│ │ │ │ │ ├── minion_silvermoon_guardian.json
│ │ │ │ │ ├── minion_southsea_captain.json
│ │ │ │ │ ├── minion_southsea_deckhand.json
│ │ │ │ │ ├── minion_spellbreaker.json
│ │ │ │ │ ├── minion_spiteful_smith.json
│ │ │ │ │ ├── minion_stampeding_kodo.json
│ │ │ │ │ ├── minion_stranglethorn_tiger.json
│ │ │ │ │ ├── minion_sunfury_protector.json
│ │ │ │ │ ├── minion_sunwalker.json
│ │ │ │ │ ├── minion_tauren_warrior.json
│ │ │ │ │ ├── minion_the_beast.json
│ │ │ │ │ ├── minion_the_black_knight.json
│ │ │ │ │ ├── minion_thrallmar_farseer.json
│ │ │ │ │ ├── minion_tinkmaster_overspark.json
│ │ │ │ │ ├── minion_twilight_drake.json
│ │ │ │ │ ├── minion_venture_co_mercenary.json
│ │ │ │ │ ├── minion_violet_teacher.json
│ │ │ │ │ ├── minion_wild_pyromancer.json
│ │ │ │ │ ├── minion_windfury_harpy.json
│ │ │ │ │ ├── minion_wisp.json
│ │ │ │ │ ├── minion_worgen_infiltrator.json
│ │ │ │ │ ├── minion_young_dragonhawk.json
│ │ │ │ │ ├── minion_young_priestess.json
│ │ │ │ │ ├── minion_youthful_brewmaster.json
│ │ │ │ │ ├── minion_ysera.json
│ │ │ │ │ ├── spell_bananas.json
│ │ │ │ │ ├── spell_dream.json
│ │ │ │ │ ├── spell_nightmare.json
│ │ │ │ │ ├── spell_ysera_awakens.json
│ │ │ │ │ ├── token_baine_bloodhoof.json
│ │ │ │ │ ├── token_chicken.json
│ │ │ │ │ ├── token_damaged_golem.json
│ │ │ │ │ ├── token_devilsaur.json
│ │ │ │ │ ├── token_emerald_drake.json
│ │ │ │ │ ├── token_finkle_einhorn.json
│ │ │ │ │ ├── token_flame_of_azzinoth.json
│ │ │ │ │ ├── token_gnoll.json
│ │ │ │ │ ├── token_imp.json
│ │ │ │ │ ├── token_laughing_sister.json
│ │ │ │ │ ├── token_murloc.json
│ │ │ │ │ ├── token_squire.json
│ │ │ │ │ ├── token_squirrel.json
│ │ │ │ │ ├── token_violet_apprentice.json
│ │ │ │ │ └── token_whelp.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── minion_aldor_peacekeeper.json
│ │ │ │ │ ├── minion_argent_protector.json
│ │ │ │ │ ├── minion_tirion_fordring.json
│ │ │ │ │ ├── secret_eye_for_an_eye.json
│ │ │ │ │ ├── secret_noble_sacrifice.json
│ │ │ │ │ ├── secret_redemption.json
│ │ │ │ │ ├── secret_repentance.json
│ │ │ │ │ ├── spell_avenging_wrath.json
│ │ │ │ │ ├── spell_blessed_champion.json
│ │ │ │ │ ├── spell_blessing_of_wisdom.json
│ │ │ │ │ ├── spell_divine_favor.json
│ │ │ │ │ ├── spell_equality.json
│ │ │ │ │ ├── spell_holy_wrath.json
│ │ │ │ │ ├── spell_lay_on_hands.json
│ │ │ │ │ ├── token_defender.json
│ │ │ │ │ ├── weapon_ashbringer.json
│ │ │ │ │ └── weapon_sword_of_justice.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── hero_power_mind_shatter.json
│ │ │ │ │ ├── hero_power_mind_spike.json
│ │ │ │ │ ├── minion_auchenai_soulpriest.json
│ │ │ │ │ ├── minion_cabal_shadow_priest.json
│ │ │ │ │ ├── minion_lightspawn.json
│ │ │ │ │ ├── minion_lightwell.json
│ │ │ │ │ ├── minion_prophet_velen.json
│ │ │ │ │ ├── minion_temple_enforcer.json
│ │ │ │ │ ├── spell_circle_of_healing.json
│ │ │ │ │ ├── spell_holy_fire.json
│ │ │ │ │ ├── spell_inner_fire.json
│ │ │ │ │ ├── spell_mass_dispel.json
│ │ │ │ │ ├── spell_mindgames.json
│ │ │ │ │ ├── spell_shadow_madness.json
│ │ │ │ │ ├── spell_shadowform.json
│ │ │ │ │ ├── spell_silence.json
│ │ │ │ │ ├── spell_thoughtsteal.json
│ │ │ │ │ └── token_shadow_of_nothing.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── minion_defias_ringleader.json
│ │ │ │ │ ├── minion_edwin_vancleef.json
│ │ │ │ │ ├── minion_kidnapper.json
│ │ │ │ │ ├── minion_master_of_disguise.json
│ │ │ │ │ ├── minion_patient_assassin.json
│ │ │ │ │ ├── minion_si7_agent.json
│ │ │ │ │ ├── spell_betrayal.json
│ │ │ │ │ ├── spell_blade_flurry.json
│ │ │ │ │ ├── spell_cold_blood.json
│ │ │ │ │ ├── spell_eviscerate.json
│ │ │ │ │ ├── spell_headcrack.json
│ │ │ │ │ ├── spell_preparation.json
│ │ │ │ │ ├── spell_shadowstep.json
│ │ │ │ │ ├── token_defias_bandit.json
│ │ │ │ │ └── weapon_perditions_blade.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── minion_al_akir_the_windlord.json
│ │ │ │ │ ├── minion_dust_devil.json
│ │ │ │ │ ├── minion_earth_elemental.json
│ │ │ │ │ ├── minion_mana_tide_totem.json
│ │ │ │ │ ├── minion_unbound_elemental.json
│ │ │ │ │ ├── spell_ancestral_spirit.json
│ │ │ │ │ ├── spell_earth_shock.json
│ │ │ │ │ ├── spell_far_sight.json
│ │ │ │ │ ├── spell_feral_spirit.json
│ │ │ │ │ ├── spell_forked_lightning.json
│ │ │ │ │ ├── spell_lava_burst.json
│ │ │ │ │ ├── spell_lightning_bolt.json
│ │ │ │ │ ├── spell_lightning_storm.json
│ │ │ │ │ ├── token_spirit_wolf.json
│ │ │ │ │ ├── weapon_doomhammer.json
│ │ │ │ │ └── weapon_stormforged_axe.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── hero_jaraxxus.json
│ │ │ │ │ ├── hero_power_inferno.json
│ │ │ │ │ ├── minion_blood_imp.json
│ │ │ │ │ ├── minion_doomguard.json
│ │ │ │ │ ├── minion_felguard.json
│ │ │ │ │ ├── minion_flame_imp.json
│ │ │ │ │ ├── minion_lord_jaraxxus.json
│ │ │ │ │ ├── minion_pit_lord.json
│ │ │ │ │ ├── minion_summoning_portal.json
│ │ │ │ │ ├── minion_void_terror.json
│ │ │ │ │ ├── spell_bane_of_doom.json
│ │ │ │ │ ├── spell_demonfire.json
│ │ │ │ │ ├── spell_sense_demons.json
│ │ │ │ │ ├── spell_shadowflame.json
│ │ │ │ │ ├── spell_siphon_soul.json
│ │ │ │ │ ├── spell_twisting_nether.json
│ │ │ │ │ ├── token_infernal.json
│ │ │ │ │ ├── token_worthless_imp.json
│ │ │ │ │ └── weapon_blood_fury.json
│ │ │ │ └── warrior/
│ │ │ │ ├── minion_arathi_weaponsmith.json
│ │ │ │ ├── minion_armorsmith.json
│ │ │ │ ├── minion_cruel_taskmaster.json
│ │ │ │ ├── minion_frothing_berserker.json
│ │ │ │ ├── minion_grommash_hellscream.json
│ │ │ │ ├── spell_battle_rage.json
│ │ │ │ ├── spell_brawl.json
│ │ │ │ ├── spell_commanding_shout.json
│ │ │ │ ├── spell_inner_rage.json
│ │ │ │ ├── spell_mortal_strike.json
│ │ │ │ ├── spell_rampage.json
│ │ │ │ ├── spell_shield_slam.json
│ │ │ │ ├── spell_slam.json
│ │ │ │ ├── spell_upgrade.json
│ │ │ │ ├── weapon_battle_axe.json
│ │ │ │ ├── weapon_gorehowl.json
│ │ │ │ └── weapon_heavy_axe.json
│ │ │ ├── goblins_vs_gnomes/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── minion_anodized_robo_cub.json
│ │ │ │ │ ├── minion_druid_of_the_fang.json
│ │ │ │ │ ├── minion_grove_tender.json
│ │ │ │ │ ├── minion_malorne.json
│ │ │ │ │ ├── minion_mech-bear-cat.json
│ │ │ │ │ ├── spell_dark_wispers.json
│ │ │ │ │ ├── spell_dark_wispers_1.json
│ │ │ │ │ ├── spell_dark_wispers_2.json
│ │ │ │ │ ├── spell_dark_wispers_3.json
│ │ │ │ │ ├── spell_recycle.json
│ │ │ │ │ ├── spell_tree_of_life.json
│ │ │ │ │ └── token_cobra_form.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── minion_gahzrilla.json
│ │ │ │ │ ├── minion_king_of_beasts.json
│ │ │ │ │ ├── minion_metaltooth_leaper.json
│ │ │ │ │ ├── minion_steamwheedle_sniper.json
│ │ │ │ │ ├── spell_call_pet.json
│ │ │ │ │ ├── spell_cobra_shot.json
│ │ │ │ │ ├── spell_feign_death.json
│ │ │ │ │ └── weapon_glaivezooka.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── minion_flame_leviathan.json
│ │ │ │ │ ├── minion_goblin_blastmage.json
│ │ │ │ │ ├── minion_snowchugger.json
│ │ │ │ │ ├── minion_soot_spewer.json
│ │ │ │ │ ├── minion_wee_spellstopper.json
│ │ │ │ │ ├── spell_echo_of_medivh.json
│ │ │ │ │ ├── spell_flamecannon.json
│ │ │ │ │ └── spell_unstable_portal.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_annoy-o-tron.json
│ │ │ │ │ ├── minion_antique_healbot.json
│ │ │ │ │ ├── minion_arcane_nullifier_x-21.json
│ │ │ │ │ ├── minion_blingtron_3000.json
│ │ │ │ │ ├── minion_bomb_lobber.json
│ │ │ │ │ ├── minion_burly_rockjaw_trogg.json
│ │ │ │ │ ├── minion_clockwork_giant.json
│ │ │ │ │ ├── minion_clockwork_gnome.json
│ │ │ │ │ ├── minion_cogmaster.json
│ │ │ │ │ ├── minion_dr_boom.json
│ │ │ │ │ ├── minion_enhance-o_mechano.json
│ │ │ │ │ ├── minion_explosive_sheep.json
│ │ │ │ │ ├── minion_fel_reaver.json
│ │ │ │ │ ├── minion_flying_machine.json
│ │ │ │ │ ├── minion_foe_reaper_4000.json
│ │ │ │ │ ├── minion_force-tank_max.json
│ │ │ │ │ ├── minion_gazlowe.json
│ │ │ │ │ ├── minion_gilblin_stalker.json
│ │ │ │ │ ├── minion_gnomeregan_infantry.json
│ │ │ │ │ ├── minion_gnomish_experimenter.json
│ │ │ │ │ ├── minion_goblin_sapper.json
│ │ │ │ │ ├── minion_hemet_nesingwary.json
│ │ │ │ │ ├── minion_hobgoblin.json
│ │ │ │ │ ├── minion_illuminator.json
│ │ │ │ │ ├── minion_jeeves.json
│ │ │ │ │ ├── minion_junkbot.json
│ │ │ │ │ ├── minion_kezan_mystic.json
│ │ │ │ │ ├── minion_lil_exorcist.json
│ │ │ │ │ ├── minion_lost_tallstrider.json
│ │ │ │ │ ├── minion_madder_bomber.json
│ │ │ │ │ ├── minion_mechanical_yeti.json
│ │ │ │ │ ├── minion_mechwarper.json
│ │ │ │ │ ├── minion_mekgineer_thermaplugg.json
│ │ │ │ │ ├── minion_micro_machine.json
│ │ │ │ │ ├── minion_mimirons_head.json
│ │ │ │ │ ├── minion_mini-mage.json
│ │ │ │ │ ├── minion_mogor_the_ogre.json
│ │ │ │ │ ├── minion_ogre_brute.json
│ │ │ │ │ ├── minion_piloted_shredder.json
│ │ │ │ │ ├── minion_piloted_sky_golem.json
│ │ │ │ │ ├── minion_puddlestomper.json
│ │ │ │ │ ├── minion_recombobulator.json
│ │ │ │ │ ├── minion_salty_dog.json
│ │ │ │ │ ├── minion_ships_cannon.json
│ │ │ │ │ ├── minion_sneeds_old_shredder.json
│ │ │ │ │ ├── minion_spider_tank.json
│ │ │ │ │ ├── minion_stonesplinter_trogg.json
│ │ │ │ │ ├── minion_target_dummy.json
│ │ │ │ │ ├── minion_tinkertown_technician.json
│ │ │ │ │ ├── minion_toshley.json
│ │ │ │ │ ├── minion_troggzor_the_earthinator.json
│ │ │ │ │ ├── token_boom_bot.json
│ │ │ │ │ ├── token_chicken_gvg.json
│ │ │ │ │ └── token_v-07-tr-0n.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── minion_bolvar_fordragon.json
│ │ │ │ │ ├── minion_cobalt_guardian.json
│ │ │ │ │ ├── minion_quartermaster.json
│ │ │ │ │ ├── minion_scarlet_purifier.json
│ │ │ │ │ ├── minion_shielded_minibot.json
│ │ │ │ │ ├── spell_muster_for_battle.json
│ │ │ │ │ ├── spell_seal_of_light.json
│ │ │ │ │ └── weapon_coghammer.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── minion_shadowbomber.json
│ │ │ │ │ ├── minion_shadowboxer.json
│ │ │ │ │ ├── minion_shrinkmeister.json
│ │ │ │ │ ├── minion_upgraded_repair_bot.json
│ │ │ │ │ ├── minion_voljin.json
│ │ │ │ │ ├── spell_light_of_the_naaru.json
│ │ │ │ │ ├── spell_lightbomb.json
│ │ │ │ │ └── spell_velens_chosen.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── minion_goblin_auto-barber.json
│ │ │ │ │ ├── minion_iron_sensei.json
│ │ │ │ │ ├── minion_ogre_ninja.json
│ │ │ │ │ ├── minion_one-eyed_cheat.json
│ │ │ │ │ ├── minion_trade_prince_gallywix.json
│ │ │ │ │ ├── spell_gallywixs_coin.json
│ │ │ │ │ ├── spell_sabotage.json
│ │ │ │ │ ├── spell_tinkers_sharpsword_oil.json
│ │ │ │ │ └── weapon_cogmasters_wrench.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── minion_dunemaul_shaman.json
│ │ │ │ │ ├── minion_neptulon.json
│ │ │ │ │ ├── minion_siltfin_spiritwalker.json
│ │ │ │ │ ├── minion_vitality_totem.json
│ │ │ │ │ ├── minion_whirling_zap-o-matic.json
│ │ │ │ │ ├── spell_ancestors_call.json
│ │ │ │ │ ├── spell_crackle.json
│ │ │ │ │ └── weapon_powermace.json
│ │ │ │ ├── spare_parts/
│ │ │ │ │ ├── spell_armor_plating.json
│ │ │ │ │ ├── spell_emergency_coolant.json
│ │ │ │ │ ├── spell_finicky_cloakfield.json
│ │ │ │ │ ├── spell_reversing_switch.json
│ │ │ │ │ ├── spell_rusty_horn.json
│ │ │ │ │ ├── spell_time_rewinder.json
│ │ │ │ │ └── spell_whirling_blades.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── minion_anima_golem.json
│ │ │ │ │ ├── minion_fel_cannon.json
│ │ │ │ │ ├── minion_floating_watcher.json
│ │ │ │ │ ├── minion_malganis.json
│ │ │ │ │ ├── minion_mistress_of_pain.json
│ │ │ │ │ ├── spell_darkbomb.json
│ │ │ │ │ ├── spell_demonheart.json
│ │ │ │ │ └── spell_imp-losion.json
│ │ │ │ └── warrior/
│ │ │ │ ├── minion_iron_juggernaut.json
│ │ │ │ ├── minion_screwjank_clunker.json
│ │ │ │ ├── minion_shieldmaiden.json
│ │ │ │ ├── minion_siege_engine.json
│ │ │ │ ├── minion_warbot.json
│ │ │ │ ├── spell_bouncing_blade.json
│ │ │ │ ├── spell_burrowing_mine.json
│ │ │ │ ├── spell_crush.json
│ │ │ │ └── weapon_ogre_warmaul.json
│ │ │ ├── hall_of_fame/
│ │ │ │ ├── minion_azure_drake.json
│ │ │ │ ├── minion_captains_parrot.json
│ │ │ │ ├── minion_elite_tauren_chieftain.json
│ │ │ │ ├── minion_gelbin_mekkatorque.json
│ │ │ │ ├── minion_old_murk-eye.json
│ │ │ │ ├── minion_ragnaros_the_firelord.json
│ │ │ │ ├── minion_sylvanas_windrunner.json
│ │ │ │ ├── spell_conceal.json
│ │ │ │ ├── spell_ice_lance.json
│ │ │ │ └── spell_power_overwhelming.json
│ │ │ ├── league_of_explorers/
│ │ │ │ ├── minion_ancient_shade.json
│ │ │ │ ├── minion_animated_armor.json
│ │ │ │ ├── minion_anubisath_sentinel.json
│ │ │ │ ├── minion_archthief_rafaam.json
│ │ │ │ ├── minion_brann_bronzebeard.json
│ │ │ │ ├── minion_dark_peddler.json
│ │ │ │ ├── minion_desert_camel.json
│ │ │ │ ├── minion_djinni_of_zephyrs.json
│ │ │ │ ├── minion_eerie_statue.json
│ │ │ │ ├── minion_elise_starseeker.json
│ │ │ │ ├── minion_ethereal_conjurer.json
│ │ │ │ ├── minion_fierce_monkey.json
│ │ │ │ ├── minion_fossilized_devilsaur.json
│ │ │ │ ├── minion_gorillabot_a3.json
│ │ │ │ ├── minion_huge_toad.json
│ │ │ │ ├── minion_jeweled_scarab.json
│ │ │ │ ├── minion_jungle_moonkin.json
│ │ │ │ ├── minion_keeper_of_uldaman.json
│ │ │ │ ├── minion_mounted_raptor.json
│ │ │ │ ├── minion_murloc_tinyfin.json
│ │ │ │ ├── minion_museum_curator.json
│ │ │ │ ├── minion_naga_sea_witch.json
│ │ │ │ ├── minion_obsidian_destroyer.json
│ │ │ │ ├── minion_pit_snake.json
│ │ │ │ ├── minion_reliquary_seeker.json
│ │ │ │ ├── minion_reno_jackson.json
│ │ │ │ ├── minion_rumbling_elemental.json
│ │ │ │ ├── minion_sir_finley_mrrgglton.json
│ │ │ │ ├── minion_summoning_stone.json
│ │ │ │ ├── minion_tomb_pillager.json
│ │ │ │ ├── minion_tomb_spider.json
│ │ │ │ ├── minion_tunnel_trogg.json
│ │ │ │ ├── minion_unearthed_raptor.json
│ │ │ │ ├── minion_wobbling_runts.json
│ │ │ │ ├── secret_dart_trap.json
│ │ │ │ ├── secret_sacred_trial.json
│ │ │ │ ├── spell_ancient_curse.json
│ │ │ │ ├── spell_anyfin_can_happen.json
│ │ │ │ ├── spell_curse_of_rafaam.json
│ │ │ │ ├── spell_cursed.json
│ │ │ │ ├── spell_entomb.json
│ │ │ │ ├── spell_everyfin_is_awesome.json
│ │ │ │ ├── spell_excavated_evil.json
│ │ │ │ ├── spell_explorers_hat.json
│ │ │ │ ├── spell_forgotten_torch.json
│ │ │ │ ├── spell_lantern_of_power.json
│ │ │ │ ├── spell_map_to_the_golden_monkey.json
│ │ │ │ ├── spell_mirror_of_doom.json
│ │ │ │ ├── spell_raven_idol.json
│ │ │ │ ├── spell_raven_idol_1.json
│ │ │ │ ├── spell_raven_idol_2.json
│ │ │ │ ├── spell_raven_idol_3.json
│ │ │ │ ├── spell_roaring_torch.json
│ │ │ │ ├── spell_timepiece_of_horror.json
│ │ │ │ ├── token_golden_monkey.json
│ │ │ │ ├── token_grumbly_runt.json
│ │ │ │ ├── token_mummy_zombie.json
│ │ │ │ ├── token_rascally_runt.json
│ │ │ │ ├── token_scarab.json
│ │ │ │ ├── token_wily_runt.json
│ │ │ │ └── weapon_cursed_blade.json
│ │ │ ├── mean_streets_of_gadgetzan/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── minion_celestial_dreamer.json
│ │ │ │ │ ├── minion_jade_behemoth.json
│ │ │ │ │ ├── minion_kun_the_forgotten_king.json
│ │ │ │ │ ├── minion_virmen_sensei.json
│ │ │ │ │ ├── spell_jade_blossom.json
│ │ │ │ │ ├── spell_jade_idol.json
│ │ │ │ │ ├── spell_jade_idol_1.json
│ │ │ │ │ ├── spell_jade_idol_2.json
│ │ │ │ │ ├── spell_jade_idol_3.json
│ │ │ │ │ ├── spell_lunar_visions.json
│ │ │ │ │ ├── spell_mark_of_the_lotus.json
│ │ │ │ │ └── spell_pilfered_power.json
│ │ │ │ ├── grimy_goons/
│ │ │ │ │ ├── minion_don_hancho.json
│ │ │ │ │ ├── minion_grimestreet_informant.json
│ │ │ │ │ └── minion_grimestreet_smuggler.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── minion_alleycat.json
│ │ │ │ │ ├── minion_dispatch_kodo.json
│ │ │ │ │ ├── minion_knuckles.json
│ │ │ │ │ ├── minion_rat_pack.json
│ │ │ │ │ ├── minion_shaky_zipgunner.json
│ │ │ │ │ ├── minion_trogg_beastrager.json
│ │ │ │ │ ├── secret_hidden_cache.json
│ │ │ │ │ ├── spell_smugglers_crate.json
│ │ │ │ │ ├── token_piranha.json
│ │ │ │ │ ├── token_rat.json
│ │ │ │ │ ├── token_tabbycat.json
│ │ │ │ │ └── weapon_piranha_launcher.json
│ │ │ │ ├── jade_lotus/
│ │ │ │ │ ├── minion_aya_blackpaw.json
│ │ │ │ │ ├── minion_jade_spirit.json
│ │ │ │ │ └── minion_lotus_agents.json
│ │ │ │ ├── kabal/
│ │ │ │ │ ├── minion_kabal_chemist.json
│ │ │ │ │ ├── minion_kabal_courier.json
│ │ │ │ │ ├── minion_kazakus.json
│ │ │ │ │ ├── token_greater_demon.json
│ │ │ │ │ ├── token_kabal_sheep.json
│ │ │ │ │ ├── token_lesser_demon.json
│ │ │ │ │ └── token_superior_demon.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── hero_baaraxxus.json
│ │ │ │ │ ├── minion_cryomancer.json
│ │ │ │ │ ├── minion_inkmaster_solia.json
│ │ │ │ │ ├── minion_kabal_crystal_runner.json
│ │ │ │ │ ├── minion_kabal_lackey.json
│ │ │ │ │ ├── minion_manic_soulcaster.json
│ │ │ │ │ ├── secret_potion_of_polymorph.json
│ │ │ │ │ ├── spell_freezing_potion.json
│ │ │ │ │ ├── spell_greater_arcane_missiles.json
│ │ │ │ │ └── spell_volcanic_potion.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_ancient_of_blossoms.json
│ │ │ │ │ ├── minion_auctionmaster_beardo.json
│ │ │ │ │ ├── minion_backroom_bouncer.json
│ │ │ │ │ ├── minion_backstreet_leper.json
│ │ │ │ │ ├── minion_big-time_racketeer.json
│ │ │ │ │ ├── minion_blowgill_sniper.json
│ │ │ │ │ ├── minion_blubber_baron.json
│ │ │ │ │ ├── minion_bomb_squad.json
│ │ │ │ │ ├── minion_burgly_bully.json
│ │ │ │ │ ├── minion_daring_reporter.json
│ │ │ │ │ ├── minion_defias_cleaner.json
│ │ │ │ │ ├── minion_dirty_rat.json
│ │ │ │ │ ├── minion_doppelgangster.json
│ │ │ │ │ ├── minion_fel_orc_soulfiend.json
│ │ │ │ │ ├── minion_fight_promoter.json
│ │ │ │ │ ├── minion_finja_the_flying_star.json
│ │ │ │ │ ├── minion_friendly_bartender.json
│ │ │ │ │ ├── minion_gadgetzan_socialite.json
│ │ │ │ │ ├── minion_genzo_the_shark.json
│ │ │ │ │ ├── minion_grook_fu_master.json
│ │ │ │ │ ├── minion_hired_gun.json
│ │ │ │ │ ├── minion_hozen_healer.json
│ │ │ │ │ ├── minion_kooky_chemist.json
│ │ │ │ │ ├── minion_leatherclad_hogleader.json
│ │ │ │ │ ├── minion_madam_goya.json
│ │ │ │ │ ├── minion_mayor_noggenfogger.json
│ │ │ │ │ ├── minion_mistress_of_mixtures.json
│ │ │ │ │ ├── minion_naga_corsair.json
│ │ │ │ │ ├── minion_patches_the_pirate.json
│ │ │ │ │ ├── minion_red_mana_wyrm.json
│ │ │ │ │ ├── minion_second-rate_bruiser.json
│ │ │ │ │ ├── minion_sergeant_sally.json
│ │ │ │ │ ├── minion_small-time_buccaneer.json
│ │ │ │ │ ├── minion_spiked_hogrider.json
│ │ │ │ │ ├── minion_street_trickster.json
│ │ │ │ │ ├── minion_streetwise_investigator.json
│ │ │ │ │ ├── minion_tanaris_hogchopper.json
│ │ │ │ │ ├── minion_toxic_sewer_ooze.json
│ │ │ │ │ ├── minion_weasel_tunneler.json
│ │ │ │ │ ├── minion_wind-up_burglebot.json
│ │ │ │ │ ├── minion_worgen_greaser.json
│ │ │ │ │ ├── minion_wrathion.json
│ │ │ │ │ └── token_ogre.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── minion_grimestreet_enforcer.json
│ │ │ │ │ ├── minion_grimestreet_outfitter.json
│ │ │ │ │ ├── minion_grimestreet_protector.json
│ │ │ │ │ ├── minion_grimscale_chum.json
│ │ │ │ │ ├── minion_meanstreet_marshal.json
│ │ │ │ │ ├── minion_wickerflame_burnbirstle.json
│ │ │ │ │ ├── secret_getaway_kodo.json
│ │ │ │ │ ├── spell_small-time_recruits.json
│ │ │ │ │ └── spell_smugglers_run.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── minion_drakonid_operative.json
│ │ │ │ │ ├── minion_kabal_songstealer.json
│ │ │ │ │ ├── minion_kabal_talonpriest.json
│ │ │ │ │ ├── minion_mana_geode.json
│ │ │ │ │ ├── minion_raza_the_chained.json
│ │ │ │ │ ├── spell_dragonfire_potion.json
│ │ │ │ │ ├── spell_greater_healing_potion.json
│ │ │ │ │ ├── spell_pint-size_potion.json
│ │ │ │ │ ├── spell_potion_of_madness.json
│ │ │ │ │ └── token_crystal.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── minion_gadgetzan_ferryman.json
│ │ │ │ │ ├── minion_jade_swarmer.json
│ │ │ │ │ ├── minion_lotus_assassin.json
│ │ │ │ │ ├── minion_luckydo_buccaneer.json
│ │ │ │ │ ├── minion_shadow_rager.json
│ │ │ │ │ ├── minion_shadow_sensei.json
│ │ │ │ │ ├── minion_shaku_the_collector.json
│ │ │ │ │ ├── spell_counterfeit_coin.json
│ │ │ │ │ └── spell_jade_shuriken.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── minion_jade_chieftain.json
│ │ │ │ │ ├── minion_jinyu_waterspeaker.json
│ │ │ │ │ ├── minion_lotus_illusionist.json
│ │ │ │ │ ├── minion_white_eyes.json
│ │ │ │ │ ├── spell_call_in_the_finishers.json
│ │ │ │ │ ├── spell_devolve.json
│ │ │ │ │ ├── spell_finders_keepers.json
│ │ │ │ │ ├── spell_jade_lightning.json
│ │ │ │ │ ├── token_murloc_razorgill.json
│ │ │ │ │ ├── token_the_storm_guardian.json
│ │ │ │ │ └── weapon_jade_claws.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── minion_abyssal_enforcer.json
│ │ │ │ │ ├── minion_crystalweaver.json
│ │ │ │ │ ├── minion_kabal_trafficker.json
│ │ │ │ │ ├── minion_krul_the_unshackled.json
│ │ │ │ │ ├── minion_seadevil_stinger.json
│ │ │ │ │ ├── minion_unlicensed_apothecary.json
│ │ │ │ │ ├── spell_blastcrystal_potion.json
│ │ │ │ │ ├── spell_bloodfury_potion.json
│ │ │ │ │ └── spell_felfire_potion.json
│ │ │ │ └── warrior/
│ │ │ │ ├── minion_alley_armorsmith.json
│ │ │ │ ├── minion_grimestreet_pawnbroker.json
│ │ │ │ ├── minion_grimy_gadgeteer.json
│ │ │ │ ├── minion_hobart_grapplehammer.json
│ │ │ │ ├── minion_public_defender.json
│ │ │ │ ├── spell_i_know_a_guy.json
│ │ │ │ ├── spell_sleep_with_the_fishes.json
│ │ │ │ ├── spell_stolen_goods.json
│ │ │ │ └── weapon_brass_knuckles.json
│ │ │ ├── naxxramas/
│ │ │ │ ├── minion_anubar_ambusher.json
│ │ │ │ ├── minion_baron_rivendare.json
│ │ │ │ ├── minion_dancing_swords.json
│ │ │ │ ├── minion_dark_cultist.json
│ │ │ │ ├── minion_deathlord.json
│ │ │ │ ├── minion_echoing_ooze.json
│ │ │ │ ├── minion_feugen.json
│ │ │ │ ├── minion_haunted_creeper.json
│ │ │ │ ├── minion_kelthuzad.json
│ │ │ │ ├── minion_loatheb.json
│ │ │ │ ├── minion_mad_scientist.json
│ │ │ │ ├── minion_maexxna.json
│ │ │ │ ├── minion_nerubar_weblord.json
│ │ │ │ ├── minion_nerubian_egg.json
│ │ │ │ ├── minion_shade_of_naxxramas.json
│ │ │ │ ├── minion_sludge_belcher.json
│ │ │ │ ├── minion_spectral_knight.json
│ │ │ │ ├── minion_stalagg.json
│ │ │ │ ├── minion_stoneskin_gargoyle.json
│ │ │ │ ├── minion_undertaker.json
│ │ │ │ ├── minion_unstable_ghoul.json
│ │ │ │ ├── minion_voidcaller.json
│ │ │ │ ├── minion_wailing_soul.json
│ │ │ │ ├── minion_webspinner.json
│ │ │ │ ├── minion_zombie_chow.json
│ │ │ │ ├── secret_avenge.json
│ │ │ │ ├── secret_duplicate.json
│ │ │ │ ├── spell_poison_seeds.json
│ │ │ │ ├── spell_reincarnate.json
│ │ │ │ ├── token_nerubian.json
│ │ │ │ ├── token_slime.json
│ │ │ │ ├── token_spectral_spider.json
│ │ │ │ ├── token_thaddius.json
│ │ │ │ └── weapon_deaths_bite.json
│ │ │ ├── one_night_in_karazhan/
│ │ │ │ ├── minion_arcane_anomaly.json
│ │ │ │ ├── minion_arcane_giant.json
│ │ │ │ ├── minion_arcanosmith.json
│ │ │ │ ├── minion_avian_watcher.json
│ │ │ │ ├── minion_babbling_book.json
│ │ │ │ ├── minion_barnes.json
│ │ │ │ ├── minion_book_wyrm.json
│ │ │ │ ├── minion_cloaked_huntress.json
│ │ │ │ ├── minion_deadly_fork.json
│ │ │ │ ├── minion_enchanted_raven.json
│ │ │ │ ├── minion_ethereal_peddler.json
│ │ │ │ ├── minion_ivory_knight.json
│ │ │ │ ├── minion_kindly_grandmother.json
│ │ │ │ ├── minion_malchezaars_imp.json
│ │ │ │ ├── minion_medivh_the_guardian.json
│ │ │ │ ├── minion_medivhs_valet.json
│ │ │ │ ├── minion_menagerie_magician.json
│ │ │ │ ├── minion_menagerie_warden.json
│ │ │ │ ├── minion_moat_lurker.json
│ │ │ │ ├── minion_moroes.json
│ │ │ │ ├── minion_netherspite_historian.json
│ │ │ │ ├── minion_nightbane_templar.json
│ │ │ │ ├── minion_onyx_bishop.json
│ │ │ │ ├── minion_pantry_spider.json
│ │ │ │ ├── minion_pompous_thespian.json
│ │ │ │ ├── minion_priest_of_the_feast.json
│ │ │ │ ├── minion_prince_malchezaar.json
│ │ │ │ ├── minion_runic_egg.json
│ │ │ │ ├── minion_silverware_golem.json
│ │ │ │ ├── minion_swashburglar.json
│ │ │ │ ├── minion_the_curator.json
│ │ │ │ ├── minion_violet_illusionist.json
│ │ │ │ ├── minion_wicked_witchdoctor.json
│ │ │ │ ├── minion_zoobot.json
│ │ │ │ ├── secret_cat_trick.json
│ │ │ │ ├── spell_firelands_portal.json
│ │ │ │ ├── spell_ironforge_portal.json
│ │ │ │ ├── spell_kara_kazham.json
│ │ │ │ ├── spell_maelstrom_portal.json
│ │ │ │ ├── spell_moonglade_portal.json
│ │ │ │ ├── spell_protect_the_king.json
│ │ │ │ ├── spell_purify.json
│ │ │ │ ├── spell_silvermoon_portal.json
│ │ │ │ ├── token_animated_shield.json
│ │ │ │ ├── token_big_bad_wolf.json
│ │ │ │ ├── token_broom.json
│ │ │ │ ├── token_candle.json
│ │ │ │ ├── token_cat_in_a_hat.json
│ │ │ │ ├── token_cellar_spider.json
│ │ │ │ ├── token_pawn.json
│ │ │ │ ├── token_steward.json
│ │ │ │ ├── token_teapot.json
│ │ │ │ ├── weapon_atiesh.json
│ │ │ │ ├── weapon_fools_bane.json
│ │ │ │ ├── weapon_sharp_fork.json
│ │ │ │ └── weapon_spirit_claws.json
│ │ │ ├── promo/
│ │ │ │ ├── spell_i_am_murloc.json
│ │ │ │ ├── spell_power_of_the_horde.json
│ │ │ │ ├── spell_rogues_do_it.json
│ │ │ │ ├── token_emboldener_3000.json
│ │ │ │ ├── token_homing_chicken.json
│ │ │ │ ├── token_poultryizer.json
│ │ │ │ └── token_repair_bot.json
│ │ │ ├── the_grand_tournament/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── hero_power_dire_shapeshift.json
│ │ │ │ │ ├── minion_aviana.json
│ │ │ │ │ ├── minion_darnassus_aspirant.json
│ │ │ │ │ ├── minion_druid_of_the_saber.json
│ │ │ │ │ ├── minion_knight_of_the_wild.json
│ │ │ │ │ ├── minion_savage_combatant.json
│ │ │ │ │ ├── minion_wildwalker.json
│ │ │ │ │ ├── spell_astral_communion.json
│ │ │ │ │ ├── spell_living_roots.json
│ │ │ │ │ ├── spell_living_roots_1.json
│ │ │ │ │ ├── spell_living_roots_2.json
│ │ │ │ │ ├── spell_living_roots_3.json
│ │ │ │ │ ├── spell_mulch.json
│ │ │ │ │ ├── token_sabertooth_lion.json
│ │ │ │ │ ├── token_sabertooth_panther.json
│ │ │ │ │ ├── token_sabertooth_tiger.json
│ │ │ │ │ └── token_sapling.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── hero_power_ballista_shot.json
│ │ │ │ │ ├── minion_acidmaw.json
│ │ │ │ │ ├── minion_brave_archer.json
│ │ │ │ │ ├── minion_dreadscale.json
│ │ │ │ │ ├── minion_kings_elekk.json
│ │ │ │ │ ├── minion_ram_wrangler.json
│ │ │ │ │ ├── minion_stablemaster.json
│ │ │ │ │ ├── secret_bear_trap.json
│ │ │ │ │ ├── spell_ball_of_spiders.json
│ │ │ │ │ ├── spell_lock_and_load.json
│ │ │ │ │ └── spell_powershot.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── hero_power_fireblast_rank_2.json
│ │ │ │ │ ├── minion_coldarra_drake.json
│ │ │ │ │ ├── minion_dalaran_aspirant.json
│ │ │ │ │ ├── minion_fallen_hero.json
│ │ │ │ │ ├── minion_rhonin.json
│ │ │ │ │ ├── minion_spellslinger.json
│ │ │ │ │ ├── secret_effigy.json
│ │ │ │ │ ├── spell_arcane_blast.json
│ │ │ │ │ ├── spell_flame_lance.json
│ │ │ │ │ ├── spell_polymorph_boar.json
│ │ │ │ │ └── token_mage_huffer.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_argent_horserider.json
│ │ │ │ │ ├── minion_argent_watchman.json
│ │ │ │ │ ├── minion_armored_warhorse.json
│ │ │ │ │ ├── minion_bolf_ramshield.json
│ │ │ │ │ ├── minion_boneguard_lieutenant.json
│ │ │ │ │ ├── minion_captured_jormungar.json
│ │ │ │ │ ├── minion_chillmaw.json
│ │ │ │ │ ├── minion_clockwork_knight.json
│ │ │ │ │ ├── minion_coliseum_manager.json
│ │ │ │ │ ├── minion_crowd_favorite.json
│ │ │ │ │ ├── minion_dragonhawk_rider.json
│ │ │ │ │ ├── minion_evil_heckler.json
│ │ │ │ │ ├── minion_eydis_darkbane.json
│ │ │ │ │ ├── minion_fencing_coach.json
│ │ │ │ │ ├── minion_fjola_lightbane.json
│ │ │ │ │ ├── minion_flame_juggler.json
│ │ │ │ │ ├── minion_frigid_snobold.json
│ │ │ │ │ ├── minion_frost_giant.json
│ │ │ │ │ ├── minion_gadgetzan_jouster.json
│ │ │ │ │ ├── minion_garrison_commander.json
│ │ │ │ │ ├── minion_gormok_the_impaler.json
│ │ │ │ │ ├── minion_grand_crusader.json
│ │ │ │ │ ├── minion_ice_rager.json
│ │ │ │ │ ├── minion_icehowl.json
│ │ │ │ │ ├── minion_injured_kvaldir.json
│ │ │ │ │ ├── minion_justicar_trueheart.json
│ │ │ │ │ ├── minion_kodorider.json
│ │ │ │ │ ├── minion_kvaldir_raider.json
│ │ │ │ │ ├── minion_lance_carrier.json
│ │ │ │ │ ├── minion_lights_champion.json
│ │ │ │ │ ├── minion_lowly_squire.json
│ │ │ │ │ ├── minion_maiden_of_the_lake.json
│ │ │ │ │ ├── minion_master_jouster.json
│ │ │ │ │ ├── minion_master_of_ceremonies.json
│ │ │ │ │ ├── minion_mogors_champion.json
│ │ │ │ │ ├── minion_muklas_champion.json
│ │ │ │ │ ├── minion_nexus-champion_saraad.json
│ │ │ │ │ ├── minion_north_sea_kraken.json
│ │ │ │ │ ├── minion_pit_fighter.json
│ │ │ │ │ ├── minion_recruiter.json
│ │ │ │ │ ├── minion_refreshment_vendor.json
│ │ │ │ │ ├── minion_saboteur.json
│ │ │ │ │ ├── minion_sideshow_spelleater.json
│ │ │ │ │ ├── minion_silent_knight.json
│ │ │ │ │ ├── minion_silver_hand_regent.json
│ │ │ │ │ ├── minion_skycapn_kragg.json
│ │ │ │ │ ├── minion_the_skeleton_knight.json
│ │ │ │ │ ├── minion_tournament_attendee.json
│ │ │ │ │ ├── minion_tournament_medic.json
│ │ │ │ │ ├── minion_twilight_guardian.json
│ │ │ │ │ └── token_war_kodo.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── hero_power_the_silver_hand.json
│ │ │ │ │ ├── minion_eadric_the_pure.json
│ │ │ │ │ ├── minion_murloc_knight.json
│ │ │ │ │ ├── minion_mysterious_challenger.json
│ │ │ │ │ ├── minion_tuskarr_jouster.json
│ │ │ │ │ ├── minion_warhorse_trainer.json
│ │ │ │ │ ├── secret_competitive_spirit.json
│ │ │ │ │ ├── spell_enter_the_coliseum.json
│ │ │ │ │ ├── spell_seal_of_champions.json
│ │ │ │ │ └── weapon_argent_lance.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── hero_power_heal.json
│ │ │ │ │ ├── minion_confessor_paletress.json
│ │ │ │ │ ├── minion_holy_champion.json
│ │ │ │ │ ├── minion_shadowfiend.json
│ │ │ │ │ ├── minion_spawn_of_shadows.json
│ │ │ │ │ ├── minion_wyrmrest_agent.json
│ │ │ │ │ ├── spell_confuse.json
│ │ │ │ │ ├── spell_convert.json
│ │ │ │ │ ├── spell_flash_heal.json
│ │ │ │ │ └── spell_power_word_glory.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── hero_power_poisoned_dagger.json
│ │ │ │ │ ├── minion_anubarak.json
│ │ │ │ │ ├── minion_buccaneer.json
│ │ │ │ │ ├── minion_cutpurse.json
│ │ │ │ │ ├── minion_shado-pan_rider.json
│ │ │ │ │ ├── minion_shady_dealer.json
│ │ │ │ │ ├── minion_undercity_valiant.json
│ │ │ │ │ ├── spell_ambush.json
│ │ │ │ │ ├── spell_beneath_the_ground.json
│ │ │ │ │ ├── spell_burgle.json
│ │ │ │ │ ├── weapon_poisoned_blade.json
│ │ │ │ │ └── weapon_poisoned_dagger.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── hero_power_lightning_jolt.json
│ │ │ │ │ ├── hero_power_totemic_slam.json
│ │ │ │ │ ├── minion_draenei_totemcarver.json
│ │ │ │ │ ├── minion_the_mistcaller.json
│ │ │ │ │ ├── minion_thunder_bluff_valiant.json
│ │ │ │ │ ├── minion_totem_golem.json
│ │ │ │ │ ├── minion_tuskarr_totemic.json
│ │ │ │ │ ├── spell_ancestral_knowledge.json
│ │ │ │ │ ├── spell_elemental_destruction.json
│ │ │ │ │ ├── spell_healing_wave.json
│ │ │ │ │ ├── spell_summon_healing_totem.json
│ │ │ │ │ ├── spell_summon_searing_totem.json
│ │ │ │ │ ├── spell_summon_stoneclaw_totem.json
│ │ │ │ │ ├── spell_summon_wrath_of_air_totem.json
│ │ │ │ │ └── weapon_charged_hammer.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── hero_power_soul_tap.json
│ │ │ │ │ ├── minion_dreadsteed.json
│ │ │ │ │ ├── minion_fearsome_doomguard.json
│ │ │ │ │ ├── minion_tiny_knight_of_evil.json
│ │ │ │ │ ├── minion_void_crusher.json
│ │ │ │ │ ├── minion_wilfred_fizzlebang.json
│ │ │ │ │ ├── minion_wrathguard.json
│ │ │ │ │ ├── spell_dark_bargain.json
│ │ │ │ │ ├── spell_demonfuse.json
│ │ │ │ │ └── spell_fist_of_jaraxxus.json
│ │ │ │ └── warrior/
│ │ │ │ ├── hero_power_tank_up.json
│ │ │ │ ├── minion_alexstraszas_champion.json
│ │ │ │ ├── minion_magnataur_alpha.json
│ │ │ │ ├── minion_orgrimmar_aspirant.json
│ │ │ │ ├── minion_sea_reaver.json
│ │ │ │ ├── minion_sparring_partner.json
│ │ │ │ ├── minion_varian_wrynn.json
│ │ │ │ ├── spell_bash.json
│ │ │ │ ├── spell_bolster.json
│ │ │ │ └── weapon_kings_defender.json
│ │ │ └── the_old_gods/
│ │ │ ├── druid/
│ │ │ │ ├── minion_addled_grizzly.json
│ │ │ │ ├── minion_dark_arakkoa.json
│ │ │ │ ├── minion_fandral_staghelm.json
│ │ │ │ ├── minion_forbidden_ancient.json
│ │ │ │ ├── minion_klaxxi_amber-weaver.json
│ │ │ │ ├── minion_mire_keeper.json
│ │ │ │ ├── spell_feral_rage.json
│ │ │ │ ├── spell_feral_rage_1.json
│ │ │ │ ├── spell_feral_rage_2.json
│ │ │ │ ├── spell_feral_rage_3.json
│ │ │ │ ├── spell_mark_of_yshaarj.json
│ │ │ │ ├── spell_wisps_of_the_old_gods.json
│ │ │ │ ├── spell_wisps_of_the_old_gods_1.json
│ │ │ │ ├── spell_wisps_of_the_old_gods_2.json
│ │ │ │ └── spell_wisps_of_the_old_gods_3.json
│ │ │ ├── hunter/
│ │ │ │ ├── minion_carrion_grub.json
│ │ │ │ ├── minion_fiery_bat.json
│ │ │ │ ├── minion_forlorn_stalker.json
│ │ │ │ ├── minion_giant_sand_worm.json
│ │ │ │ ├── minion_infested_wolf.json
│ │ │ │ ├── minion_princess_huhuran.json
│ │ │ │ ├── spell_call_of_the_wild.json
│ │ │ │ ├── spell_infest.json
│ │ │ │ ├── spell_on_the_hunt.json
│ │ │ │ ├── token_mastiff.json
│ │ │ │ └── token_spider.json
│ │ │ ├── mage/
│ │ │ │ ├── minion_anomalus.json
│ │ │ │ ├── minion_cult_sorcerer.json
│ │ │ │ ├── minion_demented_frostcaller.json
│ │ │ │ ├── minion_faceless_summoner.json
│ │ │ │ ├── minion_servant_of_yogg_saron.json
│ │ │ │ ├── minion_twilight_flamecaller.json
│ │ │ │ ├── spell_cabalists_tome.json
│ │ │ │ ├── spell_forbidden_flame.json
│ │ │ │ └── spell_shatter.json
│ │ │ ├── neutral/
│ │ │ │ ├── minion_aberrant_berserker.json
│ │ │ │ ├── minion_amgam_rager.json
│ │ │ │ ├── minion_ancient_harbinger.json
│ │ │ │ ├── minion_beckoner_of_evil.json
│ │ │ │ ├── minion_bilefin_tidehunter.json
│ │ │ │ ├── minion_blackwater_pirate.json
│ │ │ │ ├── minion_blood_of_the_ancient_one.json
│ │ │ │ ├── minion_bog_creeper.json
│ │ │ │ ├── minion_corrupted_healbot.json
│ │ │ │ ├── minion_corrupted_seer.json
│ │ │ │ ├── minion_crazed_worshipper.json
│ │ │ │ ├── minion_cthun.json
│ │ │ │ ├── minion_cthuns_chosen.json
│ │ │ │ ├── minion_cult_apothecary.json
│ │ │ │ ├── minion_cyclopian_horror.json
│ │ │ │ ├── minion_darkspeaker.json
│ │ │ │ ├── minion_deathwing_dragonlord.json
│ │ │ │ ├── minion_disciple_of_cthun.json
│ │ │ │ ├── minion_doomcaller.json
│ │ │ │ ├── minion_duskboar.json
│ │ │ │ ├── minion_eater_of_secrets.json
│ │ │ │ ├── minion_eldritch_horror.json
│ │ │ │ ├── minion_evolved_kobold.json
│ │ │ │ ├── minion_faceless_behemoth.json
│ │ │ │ ├── minion_faceless_shambler.json
│ │ │ │ ├── minion_grotesque_dragonhawk.json
│ │ │ │ ├── minion_hogger_doom_of_elwynn.json
│ │ │ │ ├── minion_infested_tauren.json
│ │ │ │ ├── minion_midnight_drake.json
│ │ │ │ ├── minion_mukla_tyrant_of_the_vale.json
│ │ │ │ ├── minion_nat_the_darkfisher.json
│ │ │ │ ├── minion_nerubian_prophet.json
│ │ │ │ ├── minion_nzoth_the_corruptor.json
│ │ │ │ ├── minion_polluted_hoarder.json
│ │ │ │ ├── minion_psych-o-tron.json
│ │ │ │ ├── minion_scaled_nightmare.json
│ │ │ │ ├── minion_shifter_zerus.json
│ │ │ │ ├── minion_silithid_swarmer.json
│ │ │ │ ├── minion_skeram_cultist.json
│ │ │ │ ├── minion_soggoth_the_slitherer.json
│ │ │ │ ├── minion_spawn_of_nzoth.json
│ │ │ │ ├── minion_squirming_tentacle.json
│ │ │ │ ├── minion_tentacle_of_nzoth.json
│ │ │ │ ├── minion_the_boogeymonster.json
│ │ │ │ ├── minion_twilight_elder.json
│ │ │ │ ├── minion_twilight_geomancer.json
│ │ │ │ ├── minion_twilight_summoner.json
│ │ │ │ ├── minion_twin_emperor_veklor.json
│ │ │ │ ├── minion_twisted_worgen.json
│ │ │ │ ├── minion_validated_doomsayer.json
│ │ │ │ ├── minion_yogg_saron_hopes_end.json
│ │ │ │ ├── minion_yshaarj_rage_unbound.json
│ │ │ │ ├── minion_zealous_initiate.json
│ │ │ │ ├── token_faceless_destroyer.json
│ │ │ │ ├── token_ooze.json
│ │ │ │ ├── token_tauren_slime.json
│ │ │ │ ├── token_the_ancient_one.json
│ │ │ │ └── token_twin_emperor_veknilash.json
│ │ │ ├── paladin/
│ │ │ │ ├── hero_power_the_tidal_hand.json
│ │ │ │ ├── minion_ragnaros_lightlord.json
│ │ │ │ ├── minion_selfless_hero.json
│ │ │ │ ├── minion_steward_of_darkshire.json
│ │ │ │ ├── minion_vilefin_inquisitor.json
│ │ │ │ ├── spell_a_light_in_the_darkness.json
│ │ │ │ ├── spell_divine_strength.json
│ │ │ │ ├── spell_forbidden_healing.json
│ │ │ │ ├── spell_stand_against_darkness.json
│ │ │ │ ├── token_silver_hand_murloc.json
│ │ │ │ └── weapon_rallying_blade.json
│ │ │ ├── priest/
│ │ │ │ ├── minion_darkshire_alchemist.json
│ │ │ │ ├── minion_herald_volazj.json
│ │ │ │ ├── minion_hooded_acolyte.json
│ │ │ │ ├── minion_shifting_shade.json
│ │ │ │ ├── minion_twilight_darkmender.json
│ │ │ │ ├── spell_embrace_the_shadow.json
│ │ │ │ ├── spell_forbidden_shaping.json
│ │ │ │ ├── spell_power_word_tentacles.json
│ │ │ │ └── spell_shadow_word_horror.json
│ │ │ ├── rogue/
│ │ │ │ ├── minion_blade_of_cthun.json
│ │ │ │ ├── minion_bladed_cultist.json
│ │ │ │ ├── minion_shadowcaster.json
│ │ │ │ ├── minion_southsea_squidface.json
│ │ │ │ ├── minion_undercity_huckster.json
│ │ │ │ ├── minion_xaril_poisoned_mind.json
│ │ │ │ ├── spell_bloodthistle_toxin.json
│ │ │ │ ├── spell_briarthorn_toxin.json
│ │ │ │ ├── spell_fadeleaf_toxin.json
│ │ │ │ ├── spell_firebloom_toxin.json
│ │ │ │ ├── spell_journey_below.json
│ │ │ │ ├── spell_kingsblood_toxin.json
│ │ │ │ ├── spell_shadow_strike.json
│ │ │ │ └── spell_thistle_tea.json
│ │ │ ├── shaman/
│ │ │ │ ├── minion_eternal_sentinel.json
│ │ │ │ ├── minion_flamewreathed_faceless.json
│ │ │ │ ├── minion_hallazeal_the_ascended.json
│ │ │ │ ├── minion_master_of_evolution.json
│ │ │ │ ├── minion_thing_from_below.json
│ │ │ │ ├── spell_evolve.json
│ │ │ │ ├── spell_primal_fusion.json
│ │ │ │ ├── spell_stormcrack.json
│ │ │ │ ├── token_twilight_elemental.json
│ │ │ │ └── weapon_hammer_of_twilight.json
│ │ │ ├── warlock/
│ │ │ │ ├── minion_chogall.json
│ │ │ │ ├── minion_darkshire_councilman.json
│ │ │ │ ├── minion_darkshire_librarian.json
│ │ │ │ ├── minion_possessed_villager.json
│ │ │ │ ├── minion_usher_of_souls.json
│ │ │ │ ├── spell_doom.json
│ │ │ │ ├── spell_forbidden_ritual.json
│ │ │ │ ├── spell_renounce_darkness.json
│ │ │ │ ├── spell_spreading_madness.json
│ │ │ │ ├── token_icky_tentacle.json
│ │ │ │ └── token_shadowbeast.json
│ │ │ └── warrior/
│ │ │ ├── minion_ancient_shieldbearer.json
│ │ │ ├── minion_bloodhoof_brave.json
│ │ │ ├── minion_bloodsail_cultist.json
│ │ │ ├── minion_malkorok.json
│ │ │ ├── minion_nzoths_first_mate.json
│ │ │ ├── minion_ravaging_ghoul.json
│ │ │ ├── spell_blood_to_ichor.json
│ │ │ ├── spell_blood_warriors.json
│ │ │ ├── weapon_rusty_hook.json
│ │ │ └── weapon_tentacles_for_arms.json
│ │ ├── decks/
│ │ │ ├── aggro_shaman.json
│ │ │ ├── aggrodin.json
│ │ │ ├── beastrattle_hunter.json
│ │ │ ├── burgle_rogue.json
│ │ │ ├── face_hunter.json
│ │ │ ├── freeze_mage.json
│ │ │ ├── jade_druid.json
│ │ │ ├── jade_miracle_druid.json
│ │ │ ├── jade_rogue.json
│ │ │ ├── midrange_shaman.json
│ │ │ ├── miracle_rogue.json
│ │ │ ├── pirate_warrior.json
│ │ │ ├── reno_mage.json
│ │ │ ├── reno_priest.json
│ │ │ ├── renolock.json
│ │ │ └── wild_pirate_warrior.json
│ │ ├── formats/
│ │ │ ├── all.json
│ │ │ ├── standard.json
│ │ │ └── wild.json
│ │ └── training/
│ │ ├── budeget_effective_gvg_rogue_tempo_mech_synergy.json
│ │ ├── gvg_face_hunter_season_9_legend_24_na.json
│ │ └── handlock_mechanization_____.json
│ └── test/
│ └── java/
│ └── net/
│ └── demilich/
│ └── metastone/
│ └── tests/
│ └── ValidateCards.java
├── documentation/
│ ├── attributes.txt
│ ├── card.txt
│ ├── conditions.txt
│ ├── filters.txt
│ ├── knowledge.txt
│ ├── known_issues.txt
│ ├── spells.txt
│ ├── triggers.txt
│ └── valueproviders.txt
├── game/
│ ├── build.gradle
│ ├── lib/
│ │ └── jsoup-1.10.2.jar
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── net/
│ │ └── demilich/
│ │ └── metastone/
│ │ └── game/
│ │ ├── Attribute.java
│ │ ├── Environment.java
│ │ ├── GameContext.java
│ │ ├── Player.java
│ │ ├── PlayerAttribute.java
│ │ ├── TurnState.java
│ │ ├── actions/
│ │ │ ├── ActionType.java
│ │ │ ├── BattlecryAction.java
│ │ │ ├── DiscoverAction.java
│ │ │ ├── EndTurnAction.java
│ │ │ ├── GameAction.java
│ │ │ ├── HeroPowerAction.java
│ │ │ ├── IActionSelectionListener.java
│ │ │ ├── IBattlecryCondition.java
│ │ │ ├── PhysicalAttackAction.java
│ │ │ ├── PlayCardAction.java
│ │ │ ├── PlayChooseOneCardAction.java
│ │ │ ├── PlayMinionCardAction.java
│ │ │ ├── PlayPermanentCardAction.java
│ │ │ ├── PlaySpellCardAction.java
│ │ │ └── PlayWeaponCardAction.java
│ │ ├── behaviour/
│ │ │ ├── Behaviour.java
│ │ │ ├── DoNothingBehaviour.java
│ │ │ ├── FlatMonteCarlo.java
│ │ │ ├── GreedyOptimizeMove.java
│ │ │ ├── GreedyOptimizeTurn.java
│ │ │ ├── IBehaviour.java
│ │ │ ├── NoAggressionBehaviour.java
│ │ │ ├── PlayRandomBehaviour.java
│ │ │ ├── TranspositionTable.java
│ │ │ ├── heuristic/
│ │ │ │ ├── IGameStateHeuristic.java
│ │ │ │ ├── WeightedFeature.java
│ │ │ │ └── WeightedHeuristic.java
│ │ │ ├── human/
│ │ │ │ ├── ActionGroup.java
│ │ │ │ ├── HumanActionOptions.java
│ │ │ │ ├── HumanBehaviour.java
│ │ │ │ ├── HumanMulliganOptions.java
│ │ │ │ └── HumanTargetOptions.java
│ │ │ ├── learning/
│ │ │ │ ├── Brain.java
│ │ │ │ ├── IBrain.java
│ │ │ │ └── LearningBehaviour.java
│ │ │ ├── mcts/
│ │ │ │ ├── ITreePolicy.java
│ │ │ │ ├── MonteCarloTreeSearch.java
│ │ │ │ ├── Node.java
│ │ │ │ └── UctPolicy.java
│ │ │ ├── neutralnetwork/
│ │ │ │ ├── HiddenUnit.java
│ │ │ │ ├── InputUnit.java
│ │ │ │ ├── NeuralNetwork.java
│ │ │ │ └── Unit.java
│ │ │ └── threat/
│ │ │ ├── GameStateValueBehaviour.java
│ │ │ ├── ThreatBasedHeuristic.java
│ │ │ ├── ThreatLevel.java
│ │ │ └── cuckoo/
│ │ │ ├── CuckooAgent.java
│ │ │ ├── CuckooLearner.java
│ │ │ ├── IFitnessFunction.java
│ │ │ └── WinRateFitness.java
│ │ ├── cards/
│ │ │ ├── Card.java
│ │ │ ├── CardCatalogue.java
│ │ │ ├── CardCollection.java
│ │ │ ├── CardDescType.java
│ │ │ ├── CardParseException.java
│ │ │ ├── CardParser.java
│ │ │ ├── CardSet.java
│ │ │ ├── CardType.java
│ │ │ ├── ChooseBattlecryCard.java
│ │ │ ├── ChooseOneCard.java
│ │ │ ├── HeroCard.java
│ │ │ ├── IChooseOneCard.java
│ │ │ ├── MinionCard.java
│ │ │ ├── PermanentCard.java
│ │ │ ├── QuestCard.java
│ │ │ ├── Rarity.java
│ │ │ ├── SecretCard.java
│ │ │ ├── SpellCard.java
│ │ │ ├── SummonCard.java
│ │ │ ├── WeaponCard.java
│ │ │ ├── costmodifier/
│ │ │ │ ├── CardCostModifier.java
│ │ │ │ ├── OneTurnCostModifier.java
│ │ │ │ └── ToggleCostModifier.java
│ │ │ └── desc/
│ │ │ ├── ActorCardDesc.java
│ │ │ ├── AttributeDeserializer.java
│ │ │ ├── AuraDeserializer.java
│ │ │ ├── CardCostModifierDeserializer.java
│ │ │ ├── CardDesc.java
│ │ │ ├── ChooseBattlecryCardDesc.java
│ │ │ ├── ChooseOneCardDesc.java
│ │ │ ├── ConditionDeserializer.java
│ │ │ ├── Desc.java
│ │ │ ├── FilterDeserializer.java
│ │ │ ├── HeroCardDesc.java
│ │ │ ├── HeroPowerCardDesc.java
│ │ │ ├── MinionCardDesc.java
│ │ │ ├── ParseUtils.java
│ │ │ ├── ParseValueType.java
│ │ │ ├── PermanentCardDesc.java
│ │ │ ├── QuestCardDesc.java
│ │ │ ├── SecretCardDesc.java
│ │ │ ├── SourceDeserializer.java
│ │ │ ├── SpellCardDesc.java
│ │ │ ├── SpellDeserializer.java
│ │ │ ├── SummonCardDesc.java
│ │ │ ├── ValueProviderDeserializer.java
│ │ │ └── WeaponCardDesc.java
│ │ ├── decks/
│ │ │ ├── Deck.java
│ │ │ ├── DeckFactory.java
│ │ │ ├── DeckFormat.java
│ │ │ ├── MetaDeck.java
│ │ │ ├── RandomDeck.java
│ │ │ └── validation/
│ │ │ ├── ArbitraryDeckValidator.java
│ │ │ ├── DefaultDeckValidator.java
│ │ │ └── IDeckValidator.java
│ │ ├── entities/
│ │ │ ├── Actor.java
│ │ │ ├── Entity.java
│ │ │ ├── EntityType.java
│ │ │ ├── heroes/
│ │ │ │ ├── Hero.java
│ │ │ │ ├── HeroClass.java
│ │ │ │ └── MetaHero.java
│ │ │ ├── minions/
│ │ │ │ ├── Minion.java
│ │ │ │ ├── Permanent.java
│ │ │ │ ├── Race.java
│ │ │ │ ├── RelativeToSource.java
│ │ │ │ └── Summon.java
│ │ │ └── weapons/
│ │ │ └── Weapon.java
│ │ ├── events/
│ │ │ ├── AfterPhysicalAttackEvent.java
│ │ │ ├── AfterSpellCastedEvent.java
│ │ │ ├── AfterSummonEvent.java
│ │ │ ├── ArmorGainedEvent.java
│ │ │ ├── BeforeSummonEvent.java
│ │ │ ├── BoardChangedEvent.java
│ │ │ ├── CardPlayedEvent.java
│ │ │ ├── CardRevealedEvent.java
│ │ │ ├── DamageEvent.java
│ │ │ ├── DiscardEvent.java
│ │ │ ├── DrawCardEvent.java
│ │ │ ├── EnrageChangedEvent.java
│ │ │ ├── GameEvent.java
│ │ │ ├── GameEventType.java
│ │ │ ├── GameStartEvent.java
│ │ │ ├── HealEvent.java
│ │ │ ├── HeroPowerUsedEvent.java
│ │ │ ├── JoustEvent.java
│ │ │ ├── KillEvent.java
│ │ │ ├── OverloadEvent.java
│ │ │ ├── PhysicalAttackEvent.java
│ │ │ ├── PreDamageEvent.java
│ │ │ ├── QuestPlayedEvent.java
│ │ │ ├── QuestSuccessfulEvent.java
│ │ │ ├── SecretPlayedEvent.java
│ │ │ ├── SecretRevealedEvent.java
│ │ │ ├── SilenceEvent.java
│ │ │ ├── SpellCastedEvent.java
│ │ │ ├── SummonEvent.java
│ │ │ ├── TargetAcquisitionEvent.java
│ │ │ ├── TurnEndEvent.java
│ │ │ ├── TurnStartEvent.java
│ │ │ ├── WeaponDestroyedEvent.java
│ │ │ └── WeaponEquippedEvent.java
│ │ ├── gameconfig/
│ │ │ ├── GameConfig.java
│ │ │ └── PlayerConfig.java
│ │ ├── heroes/
│ │ │ └── powers/
│ │ │ ├── HeroPower.java
│ │ │ └── HeroPowerChooseOne.java
│ │ ├── logic/
│ │ │ ├── ActionLogic.java
│ │ │ ├── CustomCloneable.java
│ │ │ ├── GameLogic.java
│ │ │ ├── MatchResult.java
│ │ │ └── TargetLogic.java
│ │ ├── spells/
│ │ │ ├── AddAttributeSpell.java
│ │ │ ├── AddDeathrattleSpell.java
│ │ │ ├── AddQuestSpell.java
│ │ │ ├── AddSecretSpell.java
│ │ │ ├── AddSpellTriggerSpell.java
│ │ │ ├── AdjacentEffectSpell.java
│ │ │ ├── AuraBuffSpell.java
│ │ │ ├── BuffHeroSpell.java
│ │ │ ├── BuffSpell.java
│ │ │ ├── BuffWeaponSpell.java
│ │ │ ├── CardCostModifierSpell.java
│ │ │ ├── CastRandomSpellSpell.java
│ │ │ ├── CastRepeatedlySpell.java
│ │ │ ├── ChangeHeroPowerSpell.java
│ │ │ ├── ChangeHeroSpell.java
│ │ │ ├── ClearOverloadSpell.java
│ │ │ ├── CloneMinionSpell.java
│ │ │ ├── ComboSpell.java
│ │ │ ├── ConditionalAttackBonusSpell.java
│ │ │ ├── ConditionalEffectSpell.java
│ │ │ ├── ConditionalSpell.java
│ │ │ ├── CopyCardSpell.java
│ │ │ ├── CopyDeathrattleSpell.java
│ │ │ ├── CopyHeroPower.java
│ │ │ ├── CreateCardSpell.java
│ │ │ ├── CreateSummonSpell.java
│ │ │ ├── DamageSpell.java
│ │ │ ├── DestroyAllExceptOneSpell.java
│ │ │ ├── DestroySecretsSpell.java
│ │ │ ├── DestroySpell.java
│ │ │ ├── DiscardCardsFromDeckSpell.java
│ │ │ ├── DiscardSpell.java
│ │ │ ├── DiscoverCardSpell.java
│ │ │ ├── DiscoverDrawSpell.java
│ │ │ ├── DiscoverFilteredCardSpell.java
│ │ │ ├── DiscoverOptionSpell.java
│ │ │ ├── DiscoverRandomCardSpell.java
│ │ │ ├── DoubleAttackSpell.java
│ │ │ ├── DrawCardAndDoSomethingSpell.java
│ │ │ ├── DrawCardSpell.java
│ │ │ ├── DrawCardUntilConditionSpell.java
│ │ │ ├── EitherOrSpell.java
│ │ │ ├── EnrageSpell.java
│ │ │ ├── EquipRandomWeaponSpell.java
│ │ │ ├── EquipWeaponSpell.java
│ │ │ ├── ForceDeathPhaseSpell.java
│ │ │ ├── FromDeckToHandSpell.java
│ │ │ ├── FumbleSpell.java
│ │ │ ├── GainManaSpell.java
│ │ │ ├── HealSpell.java
│ │ │ ├── ICardPostProcessor.java
│ │ │ ├── ICardProvider.java
│ │ │ ├── JoustSpell.java
│ │ │ ├── MetaSpell.java
│ │ │ ├── MindControlSpell.java
│ │ │ ├── MisdirectSpell.java
│ │ │ ├── MissilesSpell.java
│ │ │ ├── ModifyAttributeSpell.java
│ │ │ ├── ModifyDamageSpell.java
│ │ │ ├── ModifyDurabilitySpell.java
│ │ │ ├── ModifyMaxManaSpell.java
│ │ │ ├── MultiTargetSpell.java
│ │ │ ├── NullSpell.java
│ │ │ ├── OverrideTargetSpell.java
│ │ │ ├── PutCopyInHandSpell.java
│ │ │ ├── PutMinionOnBoardFromDeckSpell.java
│ │ │ ├── PutMinionOnBoardSpell.java
│ │ │ ├── PutRandomMinionOnBoardSpell.java
│ │ │ ├── PutRandomSecretIntoPlaySpell.java
│ │ │ ├── RandomAttackTargetSpell.java
│ │ │ ├── RandomSpellTargetSpell.java
│ │ │ ├── RandomlyCastSpell.java
│ │ │ ├── RecastSpell.java
│ │ │ ├── ReceiveCardAndDoSomethingSpell.java
│ │ │ ├── ReceiveCardSpell.java
│ │ │ ├── ReceiveRandomCardSpell.java
│ │ │ ├── RefreshHeroPowerSpell.java
│ │ │ ├── RemoveAttributeSpell.java
│ │ │ ├── RemoveCardSpell.java
│ │ │ ├── RenounceClassSpell.java
│ │ │ ├── ReplaceCardLocationSpell.java
│ │ │ ├── ResurrectFromBothSpell.java
│ │ │ ├── ResurrectSpell.java
│ │ │ ├── ReturnMinionToHandSpell.java
│ │ │ ├── RevertableSpell.java
│ │ │ ├── ReviveMinionSpell.java
│ │ │ ├── SetAttackSpell.java
│ │ │ ├── SetHeroHpSpell.java
│ │ │ ├── SetHpSpell.java
│ │ │ ├── ShuffleMinionToDeckSpell.java
│ │ │ ├── ShuffleToDeckSpell.java
│ │ │ ├── SilenceSpell.java
│ │ │ ├── Spell.java
│ │ │ ├── SpellUtils.java
│ │ │ ├── StealRandomSecretSpell.java
│ │ │ ├── SummonCopySpell.java
│ │ │ ├── SummonNewAttackTargetSpell.java
│ │ │ ├── SummonOneOneCopySpell.java
│ │ │ ├── SummonRandomMinionFilteredSpell.java
│ │ │ ├── SummonRandomNotOnBoardSpell.java
│ │ │ ├── SummonRandomSpell.java
│ │ │ ├── SummonSpell.java
│ │ │ ├── SwapAttackAndHpSpell.java
│ │ │ ├── SwapAttackSpell.java
│ │ │ ├── SwapHpSpell.java
│ │ │ ├── SwipeSpell.java
│ │ │ ├── TargetPlayer.java
│ │ │ ├── TemporaryAttackSpell.java
│ │ │ ├── TransformCardSpell.java
│ │ │ ├── TransformMinionSpell.java
│ │ │ ├── TransformToRandomMinionSpell.java
│ │ │ ├── TriggerDeathrattleSpell.java
│ │ │ ├── aura/
│ │ │ │ ├── AttributeAura.java
│ │ │ │ ├── Aura.java
│ │ │ │ ├── BuffAura.java
│ │ │ │ └── EnrageAura.java
│ │ │ ├── custom/
│ │ │ │ ├── AlarmOBotSpell.java
│ │ │ │ ├── BetrayalSpell.java
│ │ │ │ ├── FacelessSpell.java
│ │ │ │ ├── HeraldVolajzSpell.java
│ │ │ │ ├── HolyWrathSpell.java
│ │ │ │ ├── KelThuzadSpell.java
│ │ │ │ ├── MadamGoyaSpell.java
│ │ │ │ ├── MergeSpell.java
│ │ │ │ ├── MoatLurkerSpell.java
│ │ │ │ ├── PoisonSeedsSpell.java
│ │ │ │ ├── PutMiniCopyInHandSpell.java
│ │ │ │ ├── ShadowMadnessSpell.java
│ │ │ │ └── ShifterZerusSpell.java
│ │ │ ├── desc/
│ │ │ │ ├── BattlecryDesc.java
│ │ │ │ ├── ISpellConditionChecker.java
│ │ │ │ ├── SpellArg.java
│ │ │ │ ├── SpellDesc.java
│ │ │ │ ├── SpellFactory.java
│ │ │ │ ├── aura/
│ │ │ │ │ ├── AuraArg.java
│ │ │ │ │ └── AuraDesc.java
│ │ │ │ ├── condition/
│ │ │ │ │ ├── AndCondition.java
│ │ │ │ │ ├── AttributeCondition.java
│ │ │ │ │ ├── CardCountCondition.java
│ │ │ │ │ ├── CardPropertyCondition.java
│ │ │ │ │ ├── ComboCondition.java
│ │ │ │ │ ├── ComparisonCondition.java
│ │ │ │ │ ├── Condition.java
│ │ │ │ │ ├── ConditionArg.java
│ │ │ │ │ ├── ConditionDesc.java
│ │ │ │ │ ├── ControlsSecretCondition.java
│ │ │ │ │ ├── DeckContainsCondition.java
│ │ │ │ │ ├── GraveyardContainsCondition.java
│ │ │ │ │ ├── GraveyardCountCondition.java
│ │ │ │ │ ├── HasAttackedCondition.java
│ │ │ │ │ ├── HasEntitiesOnBoardCondition.java
│ │ │ │ │ ├── HasEntityCondition.java
│ │ │ │ │ ├── HasHeroPowerCondition.java
│ │ │ │ │ ├── HasWeaponCondition.java
│ │ │ │ │ ├── HighlanderDeckCondition.java
│ │ │ │ │ ├── HoldsCardCondition.java
│ │ │ │ │ ├── IsDamagedCondition.java
│ │ │ │ │ ├── IsDeadCondition.java
│ │ │ │ │ ├── ManaCostCondition.java
│ │ │ │ │ ├── ManaMaxedCondition.java
│ │ │ │ │ ├── MinionCountCondition.java
│ │ │ │ │ ├── MinionOnBoardCondition.java
│ │ │ │ │ ├── OrCondition.java
│ │ │ │ │ ├── OwnedByPlayerCondition.java
│ │ │ │ │ ├── RaceCondition.java
│ │ │ │ │ └── RandomCondition.java
│ │ │ │ ├── filter/
│ │ │ │ │ ├── AndFilter.java
│ │ │ │ │ ├── AttributeFilter.java
│ │ │ │ │ ├── CardFilter.java
│ │ │ │ │ ├── DamagedFilter.java
│ │ │ │ │ ├── EntityFilter.java
│ │ │ │ │ ├── FilterArg.java
│ │ │ │ │ ├── FilterDesc.java
│ │ │ │ │ ├── HighestAttributeFilter.java
│ │ │ │ │ ├── InDeckFilter.java
│ │ │ │ │ ├── InHandFilter.java
│ │ │ │ │ ├── Operation.java
│ │ │ │ │ ├── OrFilter.java
│ │ │ │ │ ├── RaceFilter.java
│ │ │ │ │ └── SpecificCardFilter.java
│ │ │ │ ├── manamodifier/
│ │ │ │ │ ├── CardCostModifierArg.java
│ │ │ │ │ └── CardCostModifierDesc.java
│ │ │ │ ├── source/
│ │ │ │ │ ├── CardSource.java
│ │ │ │ │ ├── DeckSource.java
│ │ │ │ │ ├── DefaultSource.java
│ │ │ │ │ ├── HandSource.java
│ │ │ │ │ ├── SourceArg.java
│ │ │ │ │ └── SourceDesc.java
│ │ │ │ ├── trigger/
│ │ │ │ │ ├── EventTriggerArg.java
│ │ │ │ │ ├── EventTriggerDesc.java
│ │ │ │ │ ├── EventTriggerDeserializer.java
│ │ │ │ │ └── TriggerDesc.java
│ │ │ │ └── valueprovider/
│ │ │ │ ├── AlgebraicOperation.java
│ │ │ │ ├── AlgebraicValueProvider.java
│ │ │ │ ├── AttributeCounter.java
│ │ │ │ ├── AttributeValueProvider.java
│ │ │ │ ├── CardCounter.java
│ │ │ │ ├── CardsPlayedValueProvider.java
│ │ │ │ ├── ConditionalValueProvider.java
│ │ │ │ ├── DeadMinionsThisTurn.java
│ │ │ │ ├── EntityCounter.java
│ │ │ │ ├── HighestAttributeValueProvider.java
│ │ │ │ ├── MinionSummonValueProvider.java
│ │ │ │ ├── PlayerAttributeValueProvider.java
│ │ │ │ ├── RandomValueProvider.java
│ │ │ │ ├── ValueProvider.java
│ │ │ │ ├── ValueProviderArg.java
│ │ │ │ └── ValueProviderDesc.java
│ │ │ └── trigger/
│ │ │ ├── AfterMinionPlayedTrigger.java
│ │ │ ├── AfterMinionSummonedTrigger.java
│ │ │ ├── AfterPhysicalAttackTrigger.java
│ │ │ ├── AfterSpellCastedTrigger.java
│ │ │ ├── ArmorGainedTrigger.java
│ │ │ ├── BeforeMinionPlayedTrigger.java
│ │ │ ├── BeforeMinionSummonedTrigger.java
│ │ │ ├── BoardChangedTrigger.java
│ │ │ ├── CardDrawnTrigger.java
│ │ │ ├── CardPlayedTrigger.java
│ │ │ ├── CardReceivedTrigger.java
│ │ │ ├── DamageCausedTrigger.java
│ │ │ ├── DamageReceivedTrigger.java
│ │ │ ├── DiscardTrigger.java
│ │ │ ├── EnrageChangedTrigger.java
│ │ │ ├── FatalDamageTrigger.java
│ │ │ ├── GameEventTrigger.java
│ │ │ ├── GameStartTrigger.java
│ │ │ ├── GameStateChangedTrigger.java
│ │ │ ├── HealingTrigger.java
│ │ │ ├── IGameEventListener.java
│ │ │ ├── InspireTrigger.java
│ │ │ ├── MinionDeathTrigger.java
│ │ │ ├── MinionPlayedTrigger.java
│ │ │ ├── MinionSummonedTrigger.java
│ │ │ ├── OverloadTrigger.java
│ │ │ ├── PhysicalAttackTrigger.java
│ │ │ ├── PreDamageTrigger.java
│ │ │ ├── QuestPlayedTrigger.java
│ │ │ ├── QuestSuccessTrigger.java
│ │ │ ├── SecretPlayedTrigger.java
│ │ │ ├── SecretRevealedTrigger.java
│ │ │ ├── SilenceTrigger.java
│ │ │ ├── SpellCastedTrigger.java
│ │ │ ├── SpellTrigger.java
│ │ │ ├── TargetAcquisitionTrigger.java
│ │ │ ├── TriggerManager.java
│ │ │ ├── TurnEndTrigger.java
│ │ │ ├── TurnStartTrigger.java
│ │ │ ├── WeaponDestroyedTrigger.java
│ │ │ ├── WeaponEquippedTrigger.java
│ │ │ └── types/
│ │ │ ├── Quest.java
│ │ │ └── Secret.java
│ │ ├── statistics/
│ │ │ ├── GameStatistics.java
│ │ │ └── Statistic.java
│ │ ├── targeting/
│ │ │ ├── CardLocation.java
│ │ │ ├── CardReference.java
│ │ │ ├── EntityReference.java
│ │ │ ├── IdFactory.java
│ │ │ ├── TargetSelection.java
│ │ │ └── TargetType.java
│ │ └── utils/
│ │ ├── GameTagUtils.java
│ │ └── TagValueType.java
│ └── test/
│ └── java/
│ └── net/
│ └── demilich/
│ └── metastone/
│ └── tests/
│ ├── AdvancedMechanicTests.java
│ ├── AuraTests.java
│ ├── BasicTests.java
│ ├── BlackrockMountainTests.java
│ ├── CardInteractionTests.java
│ ├── CloningTest.java
│ ├── DebugContext.java
│ ├── HeroPowerTest.java
│ ├── ManaTests.java
│ ├── MassTest.java
│ ├── PoisonSeedsTests.java
│ ├── SecretTest.java
│ ├── SpecialCardTests.java
│ ├── TargetingTests.java
│ ├── TechnicalTests.java
│ ├── TestAction.java
│ ├── TestBase.java
│ ├── TestMinionCard.java
│ ├── TestSecretCard.java
│ ├── TestSpellCard.java
│ ├── TheOldGodsTests.java
│ ├── WeaponTests.java
│ └── allcards/
│ ├── ClassicMageCards.java
│ └── ClassicNeutralCards.java
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── shared/
├── build.gradle
├── lib/
│ └── nitty-gritty-mvc.jar
└── src/
└── main/
└── java/
└── net/
└── demilich/
└── metastone/
├── GameNotification.java
├── NotificationProxy.java
├── game/
│ └── behaviour/
│ └── threat/
│ ├── FeatureVector.java
│ └── WeightedFeature.java
├── trainingmode/
│ ├── ITrainingDataListener.java
│ ├── RequestTrainingDataNotification.java
│ └── TrainingData.java
└── utils/
├── ICallback.java
├── IDisposable.java
├── MathUtils.java
├── MetastoneProperties.java
├── ResourceInputStream.java
├── ResourceLoader.java
├── Tuple.java
├── UserHomeMetastone.java
└── VersionInfo.java
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
bin
.settings
.classpath
.project
.gradle
.idea
test-output
report.log
/~$card_checklist.xlsx
build/
classes/
*.iml
cards/src/main/resources/metastone.properties
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
================================================
FILE: README.md
================================================
# MetaStone #
### What is it? ###
MetaStone is a simulator for the online collectible card game (CCG) Hearthstone® by Activison Blizzard written in Java. It strives to be a useful tool for card value analyzation, deck building and performance evaluation. There is also support for custom cards, allowing users to implement their own card inventions and testing them within the simulator engine. MetaStone tries to re-implement all game mechanics and rules from the original game as accurately as possible.
### What is it not? ###
This is no Hearthstone replacement or clone. Please do not request better graphical effects, sounds or anything which makes it feel more like Hearthstone. There won't be any mode to battle against other human players. This is a tool meant for advanced players; if you just want to play Hearthstone, please play the real game.
### How do I run it on Linux? ###
* Go to [Releases](https://github.com/demilich1/metastone/releases) and download the latest release (`metastone-X_Y_Z_jar.zip`).
* Extract the contents of the .zip file.
* Open the Terminal (`Ctrl+Alt+T` on Ubuntu) and access `../MetaStone-X.Y.Z/bin`.
* Execute this command: `./MetaStone`.
* Executing `sudo ./MetaStone` will execute the file as Root ("Super User"), this is not necessary though.
* You might need to make the file executable (On Ubuntu: Right Click the File -> Properties -> Permissions -> Allow executing file as program).
### Can I contribute? ###
Sure! There is still a lot to do and anybody willing to contribute is welcome
### What needs to be done? ###
- UI improvements in general are welcome
- We always need more unit tests! If you don't know what to test, take a look at http://hearthstone.gamepedia.com/Advanced_rulebook and just pick an example of card interaction from that wiki page
- Code refactorings to make the code simpler and/or faster
- There is a bug in the code and you know how to fix it? Great!
- Better AI: at the moment the most advanced AI is 'Game State Value', however it is very subpar compared to human players. A more sophisticated AI would be a huge boon
- Also consider having a look at the open issues
- Anything else you would like to improve
### How do I compile the code on my machine? ###
* NOTE **JDK 1.8 is required!**
* Clone the repo. See [https://help.github.com/articles/cloning-a-repository/](https://help.github.com/articles/cloning-a-repository/) for help.
* Open a terminal / command prompt and nagivate to your to your git repo location
* Run the application from the command line:
* Linux/Mac OSX `./gradlew run`
* Windows `gradlew.bat run`
* Note: this will download all dependecies, compile and assemble all modules and then run the app.
* Download dependecies and compile:
* Linux/Mac OSX `./gradlew compileJava`
* Windows `gradlew.bat compileJava`
* Note: this will download all dependecies and compile all modules. Usefull when developing.
* Get a list of all gradle tasks:
* Linux/Mac OSX `./gradlew tasks --all`
* Windows `gradlew.bat tasks --all`
#### Building with an IDE
* If you want to build from Eclipse, create the Eclipse project files:
* Linux/Mac OSX `./gradlew eclipse`
* Windows `gradlew.bat eclipse`
* _The above gradle task will automatically generate the `BuildConfig.java` file._
* Open Eclipse and choose `File > Import > General > Existing projects into workspace`
* Select the `Search for nested project` checkbox on the `Import Projects` screen.
* Change `Eclipse > Window > Preferences > Java > Compiler > Compiler Complience Level` to 1.8
* Change `Eclipse > Window > Preferences > Java > Compiler > Building > Circular dependencies` from `Error` to `Warning`. There is a [known bug](https://issues.gradle.org/browse/GRADLE-2200) with importing multi-module gradle projects into Eclipse. The IDE of choice for working with gradle projects is [IntelliJ IDEA](https://www.jetbrains.com/idea/).
* If you want to build from IntelliJ IDEA, create the IntelliJ project files:
* Linux/Mac OSX `./gradlew idea`
* Windows `gradlew.bat idea`
* _The above gradle task will automatically generate the `BuildConfig.java` file._
* Open IntelliJ and select `File > Open` then navigate to the project root dir.
* ***Optionally*** (advanced option), you can choose to import the project into your respective IDE from the `build.gradle` files. When doing so, you **must** manually generate the `BuildConfig.java` file. Otherwise your IDE will complain about unresolved references to `BuildConfig.java`.
* Linux/Mac OSX `./gradlew compileBuildConfig`
* Windows `gradlew.bat compileBuildConfig`
### Project structure
* MetaStone is made up of a handfull of source modules. Here's what the top level structure looks like:
```
metastone
├── app // Application UI code and resources. Depends on 'game' and 'cards' modules.
├── game // Game source code. Depends on 'shared' module.
├── shared // Shared code between 'app' and 'game' modules.
└── cards // Cards, decks and deckFormat data files.
```
* Each module can be built separately. Their respective dependencies will get compiled and pulled in at build time. For example:
* To produce a `cards.jar` file which contains all the cards, decks and deckFormat data files:
* Linux/Mac OSX `./gradlew cards:assemble`
* Windows `gradlew.bat cards:assemble`
* To build the game module and produce a `game.jar` file:
* Linux/Mac OSX `./gradlew game:assemble`
* Windows `gradlew.bat game:assemble`
* To produce a standalone distributable app binary:
* Linux/Mac OSX `./gradlew app:assemble`
* Windows `gradlew.bat app:assemble`
### How do I build my own cards? ###
**This feature is in very early stages and there is no official support yet.** There is no documentation at all. If you really want to start right now, here's how you can start:
- You can build your own cards or modify existing cards without having to fork the project!
- Card files are located in the `metastone/cards` directory. **Use these as reference!**
* Linux/Mac OSX `~/metastone/cards`
* Windows `C:\Users\[username]\Documents\metastone\cards`
* You can override the default metastone home dir by setting an environment varialble `USER_HOME_METASTONE` and specifying a new path.
* You must launch the app at least once for card data files to be copied.
- Any `.json` files you place in your `metastone/cards` folder will be parsed and treated like built-in cards.
- To learn the cards format it is highly recommended that you copy an existing card, change the `filename` and the `id` attribute (**<-- important!**) and make small changes.
- Restart MetaStone for new cards to be detected.
- If you are building out official cards or fixing existing cards, you will need to fork the project then make your changes in your repo's `metastone/cards/src/main/resources/cards` dir. Then open a [Pull Request](https://help.github.com/articles/using-pull-requests/) into the project [master](https://github.com/demilich1/metastone/tree/master) branch with your changes.
- Make sure to validate that the cards you added are well formed and can be parsed! Run the following command:
- Linux/Mac OSX `./gradlew cards:test`
- Windows `gradlew.bat cards:test`
- **The card format is subject to change; cards you create now MAY NOT work in future versions**
- In the rare chance that your card files get messed up beyond repair, you can always force the app to overwrite your local card files with the versions distributed with the app in `cards.jar`.
* _Option 1_: Delete the `~/metastone` dir.
* You **WILL LOOSE** all your changes, including **ALL new files** you may have added. DANGEROUS! MAKE A BACKUP!!
* Linux/Mac OSX `rm -rf ~/metastone`
* Windows `rmdir /s C:\Users\[username]\Documents\metastone`
* Card data files will be copied in their prestine state after you restart the app.
* _Option 2_: Edit the `~/metastone/metastone.properties` file and update the `cards.copied` property.
* delete the `cards.copied` property and save the file
* New files you may have added will NOT be affected.
* All card files that are distributed with the app will be overritten after you restart the app.
### Running tests
* The easiest way to run tests is from the command line.
* Linux/Mac OSX `./gradlew game:test`
* Windows `gradlew.bat game:test`
* You can also run tests from your favorite IDE. For example:
* In IntelliJ right click on `src/test` folder in a given module and select `Run All Tests`
* You can also run individual tests using the `-Dtest.single=[TEST NAME]` command line option.
* From the command line
* Linux/Mac OSX `./gradlew game:test -Dtest.single=SecretTest`
* Windows `gradlew.bat game:test -Dtest.single=SecretTest`
* From your IDE
* Right click on the individual test file and select `Run Test`
* If you encounter test failures open the test report file `build/reports/tests/index.html` for details on the failures
* Look [**here**](/game/src/test/java/net/demilich/metastone/tests) for list of existing game tests.
================================================
FILE: app/build.fxbuild
================================================
<?xml version="1.0" encoding="ASCII"?>
<anttasks:AntTask xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:anttasks="http://org.eclipse.fx.ide.jdt/1.0" buildDirectory="${project}/build" cssToBin="true">
<deploy height="768" width="1024" packagingFormat="exe">
<application name="JavaFxTest" mainclass="net.demilich.metastone.MetaStone" version="0.9" toolkit="fx"/>
<info title="Metastone" vendor="demilich"/>
</deploy>
<signjar/>
</anttasks:AntTask>
================================================
FILE: app/build.gradle
================================================
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'javafx-gradle-plugin'
buildscript {
dependencies {
classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '8.8.2'
}
repositories {
jcenter()
}
}
mainClassName = 'net.demilich.metastone.MetaStone'
jar {
manifest {
attributes 'Implementation-Title': rootProject.name.capitalize(),
'Implementation-Version': project.version
}
}
dependencies {
compile project(':game')
compile project(':cards')
compile files('lib/controlsfx-8.40.10-20151003.010657-492.jar')
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.4'
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5'
compile 'org.jsoup:jsoup:1.10.2'
compile 'org.controlsfx:openjfx-dialogs:1.0.2'
testCompile group: 'org.testng', name: 'testng', version: '6.+'
}
jfx {
// minimal requirement for jfxJar-task
mainClass = 'JavaFXDemo'
// minimal requirement for jfxNative-task
vendor = ''
}
test {
// enable TestNG support (default is JUnit)
useTestNG()
testLogging {
events "standardError"
}
}
================================================
FILE: app/javafx.plugin
================================================
/*
* Bootstrap script for the Gradle JavaFX Plugin.
* (based on http://plugins.jasoft.fi/vaadin.plugin)
*
* The script will add the plugin to the build script
* dependencies and apply the plugin to the project. If you do not want
* this behavior you can copy and paste the below configuration into your
* own build script and define your own repository and version for the plugin.
*/
import org.gradle.api.GradleException;
buildscript {
repositories {
mavenLocal()
maven {
name = 'BinTray'
url = 'http://dl.bintray.com/content/shemnon/javafx-gradle/'
}
maven {
name = 'CloudBees Snapshot'
url = 'http://repository-javafx-gradle-plugin.forge.cloudbees.com/snapshot'
}
ivy {
url = 'http://repository-javafx-gradle-plugin.forge.cloudbees.com/snapshot'
}
mavenCentral()
}
dependencies {
try {
assert (jfxrtDir != null)
} catch (RuntimeException re) {
ext.jfxrtDir = "."
}
ext.searchFile = {Map<String, Closure> places, List<String> searchPaths, String searchID ->
File result = null;
places.each { k, v ->
if (result != null) return;
project.logger.debug("Looking for $searchID in $k")
def dir = v()
if (dir == null) {
project.logger.debug("$k not set")
} else {
project.logger.debug("$k is $dir")
searchPaths.each { s ->
if (result != null) return;
File f = new File(dir, s);
project.logger.debug("Trying $f.path")
if (f.exists() && f.file) {
project.logger.debug("found $searchID as $result")
result = f;
}
}
}
}
if (!result?.file) {
throw new GradleException("Could not find $searchID, please set one of ${places.keySet()}");
} else {
project.logger.info("$searchID: ${result}")
return result
}
}
ext.findJFXJar = {
return searchFile([
'jfxrtDir in Gradle Properties': {jfxrtDir},
'JFXRT_HOME in System Environment': {System.env['JFXRT_HOME']},
'JAVA_HOME in System Environment': {System.env['JAVA_HOME']},
'java.home in JVM properties': {System.properties['java.home']}
],
['jfxrt.jar', 'lib/jfxrt.jar', 'lib/ext/jfxrt.jar', 'jre/lib/jfxrt.jar', 'jre/lib/ext/jfxrt.jar'],
'JavaFX Runtime Jar')
}
ext.findAntJavaFXJar = {
return searchFile([
'jfxrtDir in Gradle Properties': {jfxrtDir},
'JFXRT_HOME in System Environment': {System.env['JFXRT_HOME']},
'JAVA_HOME in System Environment': {System.env['JAVA_HOME']},
'java.home in JVM properties': {System.properties['java.home']}
],
['ant-javafx.jar', 'lib/ant-javafx.jar', '../lib/ant-javafx.jar'],
'JavaFX Packager Tools')
}
classpath 'org.bitbucket.shemnon.javafxplugin:gradle-javafx-plugin:8.1.2-SNAPSHOT'
classpath project.files(findAntJavaFXJar())
classpath project.files(findJFXJar())
}
}
if (!project.plugins.findPlugin(org.bitbucket.shemnon.javafxplugin.JavaFXPlugin)) {
project.apply(plugin: org.bitbucket.shemnon.javafxplugin.JavaFXPlugin)
}
================================================
FILE: app/manifest.json
================================================
{
"version" : "1.2.0",
"whatsNew" : [
"- added all 'One Night in Karazhan' cards"
]
}
================================================
FILE: app/src/deploy/package/windows/Metastone.iss
================================================
;This file will be executed next to the application bundle image
;I.e. current directory will contain folder Metastone with application files
[Setup]
AppId={{fxApplication}}
AppName=Metastone
AppVersion=1.2.0
AppVerName=Metastone
AppPublisher=demilich
AppComments=MetaStone
AppCopyright=Copyright (C) 2016
;AppPublisherURL=http://java.com/
;AppSupportURL=http://java.com/
;AppUpdatesURL=http://java.com/
DefaultDirName={localappdata}\Metastone
DisableStartupPrompt=Yes
DisableDirPage=No
DisableProgramGroupPage=Yes
DisableReadyPage=Yes
DisableFinishedPage=No
DisableWelcomePage=No
DefaultGroupName=MetaStone
;Optional License
LicenseFile=
;WinXP or above
MinVersion=0,5.1
OutputBaseFilename=Metastone_Installer
Compression=lzma
SolidCompression=yes
PrivilegesRequired=lowest
SetupIconFile=Metastone\Metastone.ico
UninstallDisplayIcon={app}\Metastone.ico
UninstallDisplayName=Metastone
WizardImageStretch=No
WizardSmallImageFile=Metastone-setup-icon.bmp
ArchitecturesInstallIn64BitMode=
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "Metastone\Metastone.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "Metastone\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
Name: "{group}\Metastone"; Filename: "{app}\Metastone.exe"; IconFilename: "{app}\Metastone.ico"; Check: returnTrue()
Name: "{commondesktop}\Metastone"; Filename: "{app}\Metastone.exe"; IconFilename: "{app}\Metastone.ico"; Check: returnFalse()
[Run]
Filename: "{app}\Metastone.exe"; Description: "{cm:LaunchProgram,Metastone}"; Flags: nowait postinstall skipifsilent; Check: returnTrue()
Filename: "{app}\Metastone.exe"; Parameters: "-install -svcName ""Metastone"" -svcDesc ""Metastone"" -mainExe ""Metastone.exe"" "; Check: returnFalse()
[UninstallRun]
Filename: "{app}\Metastone.exe "; Parameters: "-uninstall -svcName Metastone -stopOnUninstall"; Check: returnFalse()
[Code]
function returnTrue(): Boolean;
begin
Result := True;
end;
function returnFalse(): Boolean;
begin
Result := False;
end;
function InitializeSetup(): Boolean;
begin
// Possible future improvements:
// if version less or same => just launch app
// if upgrade => check if same app is running and wait for it to exit
// Add pack200/unpack200 support?
Result := True;
end;
================================================
FILE: app/src/main/java/net/demilich/metastone/ApplicationFacade.java
================================================
package net.demilich.metastone;
import net.demilich.nittygrittymvc.Facade;
import net.demilich.nittygrittymvc.interfaces.IFacade;
import net.demilich.metastone.gui.autoupdate.CheckForUpdateCommand;
import net.demilich.metastone.gui.battleofdecks.StartBattleOfDecksCommand;
import net.demilich.metastone.gui.deckbuilder.AddCardToDeckCommand;
import net.demilich.metastone.gui.deckbuilder.ChangeDeckNameCommand;
import net.demilich.metastone.gui.deckbuilder.DeleteDeckCommand;
import net.demilich.metastone.gui.deckbuilder.FillDeckWithRandomCardsCommand;
import net.demilich.metastone.gui.deckbuilder.FilterCardsCommand;
import net.demilich.metastone.gui.deckbuilder.ImportDeckCommand;
import net.demilich.metastone.gui.deckbuilder.LoadDeckFormatsCommand;
import net.demilich.metastone.gui.deckbuilder.LoadDecksCommand;
import net.demilich.metastone.gui.deckbuilder.RemoveCardFromDeckCommand;
import net.demilich.metastone.gui.deckbuilder.SaveDeckCommand;
import net.demilich.metastone.gui.deckbuilder.SetActiveDeckCommand;
import net.demilich.metastone.gui.deckbuilder.metadeck.AddDeckToMetaDeckCommand;
import net.demilich.metastone.gui.deckbuilder.metadeck.RemoveDeckFromMetaDeckCommand;
import net.demilich.metastone.gui.playmode.StartGameCommand;
import net.demilich.metastone.gui.playmode.animation.AnimationCompletedCommand;
import net.demilich.metastone.gui.playmode.animation.AnimationLockCommand;
import net.demilich.metastone.gui.playmode.animation.AnimationStartedCommand;
import net.demilich.metastone.gui.playmode.config.RequestDeckFormatsCommand;
import net.demilich.metastone.gui.playmode.config.RequestDecksCommand;
import net.demilich.metastone.gui.sandboxmode.commands.CreateNewSandboxCommand;
import net.demilich.metastone.gui.sandboxmode.commands.ModifyPlayerDeckCommand;
import net.demilich.metastone.gui.sandboxmode.commands.ModifyPlayerHandCommand;
import net.demilich.metastone.gui.sandboxmode.commands.PerformActionCommand;
import net.demilich.metastone.gui.sandboxmode.commands.SelectPlayerCommand;
import net.demilich.metastone.gui.sandboxmode.commands.SpawnMinionCommand;
import net.demilich.metastone.gui.sandboxmode.commands.StartPlaySandboxCommand;
import net.demilich.metastone.gui.sandboxmode.commands.StopPlaySandboxCommand;
import net.demilich.metastone.gui.simulationmode.SimulateGamesCommand;
import net.demilich.metastone.gui.trainingmode.PerformTrainingCommand;
import net.demilich.metastone.gui.trainingmode.RequestTrainingDataCommand;
import net.demilich.metastone.gui.trainingmode.SaveTrainingDataCommand;
public class ApplicationFacade extends Facade<GameNotification> {
@SuppressWarnings("unchecked")
public static IFacade<GameNotification> getInstance() {
if (instance == null) {
instance = new ApplicationFacade();
}
return instance;
}
public ApplicationFacade() {
NotificationProxy.init(this);
registerCommand(GameNotification.APPLICATION_STARTUP, new ApplicationStartupCommand());
registerCommand(GameNotification.START_GAME, new StartGameCommand());
registerCommand(GameNotification.PLAY_GAME, new PlayGameCommand());
registerCommand(GameNotification.SIMULATE_GAMES, new SimulateGamesCommand());
registerCommand(GameNotification.START_TRAINING, new PerformTrainingCommand());
registerCommand(GameNotification.COMMIT_BATTLE_OF_DECKS_CONFIG, new StartBattleOfDecksCommand());
registerCommand(GameNotification.CHECK_FOR_UPDATE, new CheckForUpdateCommand());
registerCommand(GameNotification.SET_ACTIVE_DECK, new SetActiveDeckCommand());
registerCommand(GameNotification.ADD_CARD_TO_DECK, new AddCardToDeckCommand());
registerCommand(GameNotification.REMOVE_CARD_FROM_DECK, new RemoveCardFromDeckCommand());
registerCommand(GameNotification.SAVE_ACTIVE_DECK, new SaveDeckCommand());
registerCommand(GameNotification.LOAD_DECKS, new LoadDecksCommand());
registerCommand(GameNotification.LOAD_DECK_FORMATS, new LoadDeckFormatsCommand());
registerCommand(GameNotification.FILTER_CARDS, new FilterCardsCommand());
registerCommand(GameNotification.FILL_DECK_WITH_RANDOM_CARDS, new FillDeckWithRandomCardsCommand());
registerCommand(GameNotification.IMPORT_DECK_FROM_URL, new ImportDeckCommand());
registerCommand(GameNotification.CHANGE_DECK_NAME, new ChangeDeckNameCommand());
registerCommand(GameNotification.ADD_DECK_TO_META_DECK, new AddDeckToMetaDeckCommand());
registerCommand(GameNotification.REMOVE_DECK_FROM_META_DECK, new RemoveDeckFromMetaDeckCommand());
registerCommand(GameNotification.DELETE_DECK, new DeleteDeckCommand());
registerCommand(GameNotification.REQUEST_DECKS, new RequestDecksCommand());
registerCommand(GameNotification.REQUEST_DECK_FORMATS, new RequestDeckFormatsCommand());
registerCommand(GameNotification.CREATE_NEW_SANDBOX, new CreateNewSandboxCommand());
registerCommand(GameNotification.MODIFY_PLAYER_DECK, new ModifyPlayerDeckCommand());
registerCommand(GameNotification.MODIFY_PLAYER_HAND, new ModifyPlayerHandCommand());
registerCommand(GameNotification.SELECT_PLAYER, new SelectPlayerCommand());
registerCommand(GameNotification.SPAWN_MINION, new SpawnMinionCommand());
registerCommand(GameNotification.PERFORM_ACTION, new PerformActionCommand());
registerCommand(GameNotification.START_PLAY_SANDBOX, new StartPlaySandboxCommand());
registerCommand(GameNotification.STOP_PLAY_SANDBOX, new StopPlaySandboxCommand());
registerCommand(GameNotification.GAME_STATE_UPDATE, new AnimationLockCommand());
registerCommand(GameNotification.ANIMATION_STARTED, new AnimationStartedCommand());
registerCommand(GameNotification.ANIMATION_COMPLETED, new AnimationCompletedCommand());
registerCommand(GameNotification.SAVE_TRAINING_DATA, new SaveTrainingDataCommand());
registerCommand(GameNotification.REQUEST_TRAINING_DATA, new RequestTrainingDataCommand());
}
public void startUp() {
sendNotification(GameNotification.APPLICATION_STARTUP);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/ApplicationStartupCommand.java
================================================
package net.demilich.metastone;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.gui.cards.CardProxy;
import net.demilich.metastone.gui.autoupdate.AutoUpdateMediator;
import net.demilich.metastone.gui.deckbuilder.DeckFormatProxy;
import net.demilich.metastone.gui.deckbuilder.DeckProxy;
import net.demilich.metastone.gui.dialog.DialogMediator;
import net.demilich.metastone.gui.main.ApplicationMediator;
import net.demilich.metastone.gui.playmode.animation.AnimationProxy;
import net.demilich.metastone.gui.sandboxmode.SandboxProxy;
import net.demilich.metastone.gui.trainingmode.TrainingProxy;
public class ApplicationStartupCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
getFacade().registerMediator(new DialogMediator());
getFacade().registerProxy(new CardProxy());
getFacade().registerProxy(new DeckProxy());
getFacade().registerProxy(new DeckFormatProxy());
getFacade().registerProxy(new TrainingProxy());
getFacade().registerProxy(new SandboxProxy());
getFacade().registerProxy(new AnimationProxy());
getFacade().registerMediator(new ApplicationMediator());
getFacade().registerMediator(new AutoUpdateMediator());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/DevCardTools.java
================================================
package net.demilich.metastone;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.commons.io.FileUtils;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardCatalogue;
/**
* TODO: not sure how this is used.
* Paths in this file are no longer valid since cards, decks and deckformat are loaded from jar resources
*/
public class DevCardTools {
public static void assignUniqueIdToEachCard() {
final String path = "./src/" + Card.class.getPackage().getName().replace(".", "/") + "/concrete/";
final String idExpression = "public int getTypeId()";
File folder = new File(path);
int uniqueId = 1;
HashSet<Integer> assignedIds = new HashSet<>();
List<File> filesWithoutId = new ArrayList<>();
for (File file : FileUtils.listFiles(folder, new String[] { "java" }, true)) {
try {
// System.out.println("Processing " + file.getName() + "...");
List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
int lineIndex = containsExpression(lines, idExpression);
if (lineIndex != -1) {
// System.out.println("Skipping " + file.getName() +
// " because it already has an id assigned");
int id = extractId(lines.get(lineIndex + 1));
assignedIds.add(id);
continue;
} else {
filesWithoutId.add(file);
}
} catch (IOException e) {
System.err.println("Error while parsing file: " + file.getName());
e.printStackTrace();
}
}
while (assignedIds.contains(uniqueId)) {
uniqueId++;
}
for (File file : filesWithoutId) {
try {
List<String> lines;
lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
for (int i = lines.size() - 1; i > 0; i--) {
String line = lines.get(i);
if (line.contains("}")) {
lines.add(i, "\t}");
lines.add(i, "\t\treturn " + uniqueId + ";");
lines.add(i, "\tpublic int getTypeId() {");
lines.add(i, "\t@Override");
lines.add(i, "\n");
System.out.println("Assigning id " + uniqueId + " to " + file.getName());
uniqueId++;
break;
}
}
Files.write(file.toPath(), lines, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void cardListFromImages(String path) throws IOException {
File folder = new File(path);
PrintWriter out = new PrintWriter(new FileWriter("cards_all"));
for (File file : folder.listFiles()) {
if (file.isFile()) {
out.println(file.getName().replace(".png", ""));
}
}
out.close();
}
private static String changeFileNameToClassName(String name) {
if (name == null) {
throw new IllegalArgumentException("File Name == null");
}
String className = name.replace(".java", "");
className = className.replace('/', '.');
className = className.replace('\\', '.');
className = className.replace("..src.", "");
return className;
}
public static void compareClassesWithCardList(String path) throws IOException {
File folder = new File(path);
BufferedReader reader = new BufferedReader(new FileReader("cards_all"));
List<String> allCards = new ArrayList<String>();
String line;
while ((line = reader.readLine()) != null) {
allCards.add(toCanonName(line));
}
reader.close();
List<String> allClasses = new ArrayList<String>();
for (File file : FileUtils.listFiles(folder, new String[] { "java" }, true)) {
String canonName = toCanonName(file.getName());
allClasses.add(canonName);
}
int missing = 0;
for (String card : allCards) {
if (allClasses.contains(card)) {
// System.out.println("Card found: " + card);
} else {
missing++;
System.out.println("Card missing: " + card);
}
}
System.out.println("There are " + missing + " cards missing");
}
private static int containsExpression(List<String> lines, String expression) {
int i = 0;
for (String line : lines) {
if (line.contains(expression)) {
return i;
}
i++;
}
return -1;
}
private static int extractId(String line) {
String result = "";
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (Character.isDigit(c)) {
result += c;
}
}
return Integer.parseInt(result);
}
public static void formatJsons() {
File folder = new File("./cards/");
Collection<File> files = FileUtils.listFiles(folder, new String[] { "json" }, true);
int i = 0;
for (File file : files) {
try {
System.out.println("Processing " + file.getName() + " (" + ++i + " of " + files.size() + " files)");
prettyPrintFile(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static List<String> getImplementedCardsAsLines() {
final String expression = "cards.add(new %s());";
final String path = "./src/" + Card.class.getPackage().getName().replace(".", "/") + "/concrete/";
List<String> lines = new ArrayList<String>();
File folder = new File(path);
for (File file : FileUtils.listFiles(folder, new String[] { "java" }, true)) {
String cardFileName = file.getPath();
String cardClassName = changeFileNameToClassName(cardFileName);
// System.out.println(changeFileNameToClassName(cardName));
lines.add(String.format(expression, cardClassName));
}
return lines;
}
private static void prettyPrintFile(File file) throws IOException {
Path path = Paths.get(file.getPath());
String content = new String(Files.readAllBytes(path));
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine scriptEngine = manager.getEngineByName("JavaScript");
scriptEngine.put("jsonString", content);
try {
scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, \"\t\")");
} catch (ScriptException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String prettyPrintedJson = (String) scriptEngine.get("result");
Files.write(path, prettyPrintedJson.getBytes());
}
private static String toCanonName(String name) {
return name.toLowerCase().replace(".java", "").replace(".png", "").replace("_", "").replace("-", "");
}
public static void updateCardCatalogue() {
final String cataloguePathStr = "./src/" + CardCatalogue.class.getPackage().getName().replace(".", "/") + "/CardCatalogue.java";
Path cataloguePath = Paths.get(cataloguePathStr);
List<String> lines = new ArrayList<>();
try (BufferedReader reader = Files.newBufferedReader(cataloguePath)) {
String line = null;
List<String> implementedCards = getImplementedCardsAsLines();
boolean insideRelevantCodeBlock = false;
while ((line = reader.readLine()) != null) {
if (line.contains("static {")) {
lines.add(line);
insideRelevantCodeBlock = true;
lines.addAll(implementedCards);
} else if (line.contains("}")) {
insideRelevantCodeBlock = false;
}
if (!insideRelevantCodeBlock) {
lines.add(line);
}
}
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
try {
Files.write(cataloguePath, lines);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("CardCatalogue has been successfully updated");
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/MetaStone.java
================================================
package net.demilich.metastone;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import net.demilich.metastone.gui.IconFactory;
import net.demilich.metastone.utils.UserHomeMetastone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class MetaStone extends Application {
private static Logger logger = LoggerFactory.getLogger(MetaStone.class);
public static void main(String[] args) {
//DevCardTools.formatJsons();
try {
// ensure that the user home metastone dir exists
Files.createDirectories(Paths.get(UserHomeMetastone.getPath()));
} catch (IOException e) {
logger.error("Trouble creating " + Paths.get(UserHomeMetastone.getPath()));
e.printStackTrace();
}
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("MetaStone");
primaryStage.initStyle(StageStyle.UNIFIED);
primaryStage.setResizable(false);
primaryStage.getIcons().add(new Image(IconFactory.getImageUrl("ui/app_icon.png")));
ApplicationFacade facade = (ApplicationFacade) ApplicationFacade.getInstance();
facade.startUp();
StackPane root = new StackPane();
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("/css/main.css").toExternalForm());
primaryStage.setScene(scene);
// implementing potential visual fix for JavaFX
// setting the visual opacity to zero, and then
// once the stage is shown, setting the opacity to one.
// this fixes an issue where some users would only see a blank
// screen on application startup
primaryStage.setOpacity(0.0);
facade.sendNotification(GameNotification.CANVAS_CREATED, root);
facade.sendNotification(GameNotification.MAIN_MENU);
primaryStage.show();
// setting opacity to one for JavaFX hotfix
primaryStage.setOpacity(1.0);
facade.sendNotification(GameNotification.CHECK_FOR_UPDATE);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/PlayGameCommand.java
================================================
package net.demilich.metastone;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.game.GameContext;
public class PlayGameCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
GameContext context = (GameContext) notification.getBody();
context.play();
getFacade().sendNotification(GameNotification.GAME_OVER, context);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/DigitFactory.java
================================================
package net.demilich.metastone.gui;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.imageio.ImageIO;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.effect.Blend;
import javafx.scene.effect.BlendMode;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.effect.ColorInput;
import javafx.scene.effect.Effect;
import javafx.scene.effect.ImageInput;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class DigitFactory {
private final static HashMap<Character, Image> digits = new HashMap<>();
static {
digits.put('-', new Image(IconFactory.RESOURCE_PATH + "/img/common/digits/-.png"));
for (int i = 0; i < 10; i++) {
char digitToChar = Character.forDigit(i, 10);
digits.put(digitToChar, new Image(IconFactory.RESOURCE_PATH + "/img/common/digits/" + digitToChar + ".png"));
}
}
private static void applyFontColor(ImageView image, Color color) {
ColorAdjust monochrome = new ColorAdjust();
monochrome.setSaturation(-1.0);
Effect colorInput = new ColorInput(0, 0, image.getImage().getWidth(), image.getImage().getHeight(), color);
Blend blend = new Blend(BlendMode.MULTIPLY, new ImageInput(image.getImage()), colorInput);
image.setClip(new ImageView(image.getImage()));
image.setEffect(blend);
image.setCache(true);
}
private static Node getCachedDigitImage(int number, Color color) {
String numberString = String.valueOf(number);
if (numberString.length() == 1) {
char digitToChar = Character.forDigit(number, 10);
ImageView image = new ImageView(digits.get(digitToChar));
applyFontColor(image, color);
return image;
}
HBox layoutPane = new HBox(-4);
for (int i = 0; i < numberString.length(); i++) {
char digitToChar = numberString.charAt(i);
ImageView image = new ImageView(digits.get(digitToChar));
applyFontColor(image, color);
layoutPane.getChildren().add(image);
}
return layoutPane;
}
public static void saveAllDigits() {
Stage stage = new Stage(StageStyle.TRANSPARENT);
DigitTemplate root = new DigitTemplate();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
SnapshotParameters snapshotParams = new SnapshotParameters();
snapshotParams.setFill(Color.TRANSPARENT);
root.digit.setText("-");
for (int i = 0; i <= 10; i++) {
WritableImage image = root.digit.snapshot(snapshotParams, null);
File file = new File("src/" + IconFactory.RESOURCE_PATH + "/img/common/digits/" + root.digit.getText() + ".png");
try {
ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", file);
} catch (IOException e) {
e.printStackTrace();
}
root.digit.setText("" + i);
}
stage.close();
}
public static void showPreRenderedDigits(Group group, int number) {
showPreRenderedDigits(group, number, Color.WHITE);
}
public static void showPreRenderedDigits(Group group, int number, Color color) {
group.getChildren().clear();
group.getChildren().add(DigitFactory.getCachedDigitImage(number, color));
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/DigitTemplate.java
================================================
package net.demilich.metastone.gui;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
public class DigitTemplate extends HBox {
@FXML
public Text digit;
public DigitTemplate() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/DigitTemplate.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/IconFactory.java
================================================
package net.demilich.metastone.gui;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import net.demilich.metastone.game.cards.Rarity;
import net.demilich.metastone.game.entities.heroes.HeroClass;
import net.demilich.metastone.game.heroes.powers.HeroPower;
import net.demilich.metastone.gui.dialog.DialogType;
public class IconFactory {
//public static final String RESOURCE_PATH = "/net/demilich/metastone/resources";
public static final String RESOURCE_PATH = "";
public static Image getClassIcon(HeroClass heroClass) {
String iconPath = RESOURCE_PATH + "/img/classes/";
iconPath += heroClass.toString().toLowerCase();
iconPath += ".png";
return new Image(iconPath);
}
public static Image getDefaultCardBack() {
String iconPath = RESOURCE_PATH + "/img/common/card_back_default.png";
return new Image(iconPath);
}
public static Image getDialogIcon(DialogType dialogType) {
String iconPath = RESOURCE_PATH + "/img/ui/";
switch (dialogType) {
case CONFIRM:
iconPath += "confirm.png";
break;
case ERROR:
iconPath += "error.png";
break;
case INFO:
iconPath += "info.png";
break;
case WARNING:
iconPath += "warning.png";
break;
default:
break;
}
return new Image(iconPath);
}
public static String getHeroIconUrl(HeroClass heroClass) {
String iconPath = RESOURCE_PATH + "/img/heroes/";
switch (heroClass) {
case DRUID:
iconPath += "malfurion";
break;
case HUNTER:
iconPath += "rexxar";
break;
case MAGE:
iconPath += "jaina";
break;
case PALADIN:
iconPath += "uther";
break;
case PRIEST:
iconPath += "anduin";
break;
case ROGUE:
iconPath += "valeera";
break;
case SHAMAN:
iconPath += "thrall";
break;
case WARLOCK:
iconPath += "guldan";
break;
case WARRIOR:
iconPath += "garrosh";
break;
default:
case ANY:
iconPath += "unknown";
break;
}
return iconPath + ".png";
}
public static String getHeroPowerIconUrl(HeroPower heroPower) {
String iconPath = RESOURCE_PATH + "/img/powers/";
switch (heroPower.getHeroClass()) {
case DRUID:
iconPath += "shapeshift";
break;
case HUNTER:
iconPath += "steady_shot";
break;
case MAGE:
iconPath += "fireblast";
break;
case PALADIN:
iconPath += "reinforce";
break;
case PRIEST:
iconPath += "lesser_heal";
break;
case ROGUE:
iconPath += "dagger_mastery";
break;
case SHAMAN:
iconPath += "totemic_call";
break;
case WARLOCK:
iconPath += "life_tap";
break;
case WARRIOR:
iconPath += "armor_up";
break;
default:
iconPath += "unknown";
break;
}
iconPath += ".png";
return iconPath;
}
public static String getImageUrl(String imageName) {
//System.out.println(new File("").getAbsolutePath());
return RESOURCE_PATH + "/img/" + imageName;
}
public static Color getRarityColor(Rarity rarity) {
Color color = Color.BLACK;
switch (rarity) {
case COMMON:
color = Color.WHITE;
break;
case EPIC:
// a335ee
color = Color.rgb(163, 53, 238);
break;
case LEGENDARY:
// ff8000
color = Color.rgb(255, 128, 0);
break;
case RARE:
// 0070dd
color = Color.rgb(0, 112, 221);
break;
default:
color = Color.GRAY;
break;
}
return color;
}
public static Image getSummonHelper() {
String iconPath = RESOURCE_PATH + "/img/common/arrow_down_blue.png";
return new Image(iconPath);
}
public static Image getTargetIcon() {
String iconPath = RESOURCE_PATH + "/img/common/target.png";
return new Image(iconPath);
}
private IconFactory() {
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/autoupdate/AutoUpdateMediator.java
================================================
package net.demilich.metastone.gui.autoupdate;
import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.controlsfx.control.Notifications;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.image.ImageView;
import javafx.util.Duration;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.gui.IconFactory;
import net.demilich.metastone.gui.dialog.DialogType;
import net.demilich.metastone.utils.VersionInfo;
import net.demilich.nittygrittymvc.Mediator;
import net.demilich.nittygrittymvc.interfaces.INotification;
public class AutoUpdateMediator extends Mediator<GameNotification> {
public static final String NAME = "AutoUpdateMediator";
private Node view;
public AutoUpdateMediator() {
super(NAME);
}
@Override
public void handleNotification(final INotification<GameNotification> notification) {
switch (notification.getId()) {
case CANVAS_CREATED:
view = (Node) notification.getBody();
break;
case NEW_VERSION_AVAILABLE:
VersionInfo versionInfo = (VersionInfo) notification.getBody();
Platform.runLater(() -> showUpdateNotification(versionInfo));
break;
default:
break;
}
}
@Override
public List<GameNotification> listNotificationInterests() {
List<GameNotification> notificationInterests = new ArrayList<GameNotification>();
notificationInterests.add(GameNotification.CANVAS_CREATED);
notificationInterests.add(GameNotification.NEW_VERSION_AVAILABLE);
return notificationInterests;
}
private void showUpdateNotification(VersionInfo versionInfo) {
ImageView icon = new ImageView(IconFactory.getDialogIcon(DialogType.INFO));
icon.setFitWidth(64);
icon.setFitHeight(64);
Notifications.create()
.title("New version available")
.text("MetaStone '" + versionInfo.version + "' is ready for download")
.graphic(icon)
.position(Pos.BOTTOM_CENTER)
.hideAfter(Duration.seconds(5))
.owner(view)
.darkStyle()
.onAction(this::onNotificationClicked)
.show();
}
private void onNotificationClicked(ActionEvent event) {
try {
Desktop.getDesktop().browse(new URI("http://www.demilich.net/metastone/download.html"));
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/autoupdate/CheckForUpdateCommand.java
================================================
package net.demilich.metastone.gui.autoupdate;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import net.demilich.metastone.BuildConfig;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.utils.VersionInfo;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
public class CheckForUpdateCommand extends SimpleCommand<GameNotification> {
private static Logger logger = LoggerFactory.getLogger(CheckForUpdateCommand .class);
private static final String MANIFEST_URL = "http://demilich.net/metastone/version/manifest.json";
@Override
public void execute(INotification<GameNotification> notification) {
new Thread(this::check).start();
}
private void check() {
try {
RequestConfig globalConfig = RequestConfig.custom().setCircularRedirectsAllowed(true).build();
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
logger.debug("Requesting: " + MANIFEST_URL);
HttpGet httpGet = new HttpGet(MANIFEST_URL);
httpGet.setConfig(globalConfig);
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
HttpEntity entity = response.getEntity();
String htmlContent = EntityUtils.toString(entity);
EntityUtils.consume(entity);
Gson gson = new Gson();
VersionInfo versionInfo = gson.fromJson(htmlContent, VersionInfo.class);
if (versionInfo.isNewerVersionAvailable(BuildConfig.VERSION)) {
logger.debug("Newer version available: {}" + versionInfo.version);
getFacade().sendNotification(GameNotification.NEW_VERSION_AVAILABLE, versionInfo);
} else {
logger.debug("Version up-to-date");
}
} finally {
response.close();
}
} catch (Exception e) {
logger.warn("Auto updater version check failed: " + e.toString());
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleBatchResult.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.statistics.GameStatistics;
import net.demilich.metastone.game.statistics.Statistic;
public class BattleBatchResult {
private final int numberOfGames;
private final GameStatistics player1Results = new GameStatistics();
private final GameStatistics player2Results = new GameStatistics();
private int gamesCompleted;
private final Deck deck1;
private final Deck deck2;
private boolean completed;
public BattleBatchResult(Deck deck1, Deck deck2, int numberOfGames) {
this.deck1 = deck1;
this.deck2 = deck2;
this.numberOfGames = numberOfGames;
}
public Deck getDeck1() {
return deck1;
}
public double getDeck1Winrate() {
return getPlayer1Results().getDouble(Statistic.WIN_RATE);
}
public Deck getDeck2() {
return deck2;
}
public double getDeck2Winrate() {
return getPlayer2Results().getDouble(Statistic.WIN_RATE);
}
public int getNumberOfGames() {
return numberOfGames;
}
public GameStatistics getPlayer1Results() {
return player1Results;
}
public GameStatistics getPlayer2Results() {
return player2Results;
}
public double getProgress() {
return gamesCompleted / (double) numberOfGames;
}
public boolean isCompleted() {
return completed;
}
public void onGameEnded(GameContext result) {
getPlayer1Results().merge(result.getPlayer1().getStatistics());
getPlayer2Results().merge(result.getPlayer2().getStatistics());
if (++gamesCompleted == numberOfGames) {
setCompleted(true);
}
}
public void setCompleted(boolean completed) {
this.completed = completed;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleBatchResultToken.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Tooltip;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import net.demilich.metastone.gui.IconFactory;
public class BattleBatchResultToken extends BorderPane {
@FXML
private Label deck1Label;
@FXML
private ImageView deck1Icon;
@FXML
private Label deck2Label;
@FXML
private ImageView deck2Icon;
@FXML
private ProgressBar winrate1Bar;
@FXML
private Label winrate1Label;
@FXML
private ProgressBar winrate2Bar;
@FXML
private Label winrate2Label;
@FXML
private Node contentPane;
@FXML
private ProgressIndicator progressIndicator;
public BattleBatchResultToken() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/BattleBatchResultToken.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
contentPane.setOpacity(0.25);
winrate1Bar.setVisible(false);
winrate1Label.setVisible(false);
winrate2Bar.setVisible(false);
winrate2Label.setVisible(false);
}
public void displayBatchResult(BattleBatchResult result) {
if (!result.isCompleted()) {
progressIndicator.setProgress(result.getProgress());
Tooltip.install(this, new Tooltip("In progress\n\n" + result.getDeck1().getName() + "\nVS.\n" + result.getDeck2().getName()));
} else if (contentPane.getOpacity() < 1) {
contentPane.setOpacity(1);
progressIndicator.setVisible(false);
winrate1Bar.setVisible(true);
winrate1Label.setVisible(true);
winrate2Bar.setVisible(true);
winrate2Label.setVisible(true);
Tooltip.install(this, null);
}
deck1Label.setText(result.getDeck1().getName());
deck1Icon.setImage(IconFactory.getClassIcon(result.getDeck1().getHeroClass()));
deck2Label.setText(result.getDeck2().getName());
deck2Icon.setImage(IconFactory.getClassIcon(result.getDeck2().getHeroClass()));
winrate1Bar.setProgress(result.getDeck1Winrate());
winrate1Label.setText(String.format("%.2f", result.getDeck1Winrate() * 100) + "%");
winrate2Bar.setProgress(result.getDeck2Winrate());
winrate2Label.setText(String.format("%.2f", result.getDeck2Winrate() * 100) + "%");
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleConfig.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import java.util.Collection;
import net.demilich.metastone.game.behaviour.IBehaviour;
import net.demilich.metastone.game.decks.Deck;
public class BattleConfig {
private final int numberOfGames;
private final IBehaviour behaviour;
private final Collection<Deck> decks;
public BattleConfig(int numberOfGames, IBehaviour behaviour, Collection<Deck> decks) {
this.numberOfGames = numberOfGames;
this.behaviour = behaviour;
this.decks = decks;
}
public IBehaviour getBehaviour() {
return behaviour;
}
public Collection<Deck> getDecks() {
return decks;
}
public int getNumberOfGames() {
return numberOfGames;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleDeckResult.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import net.demilich.metastone.game.statistics.GameStatistics;
import net.demilich.metastone.game.statistics.Statistic;
public class BattleDeckResult {
private final StringProperty deckName = new SimpleStringProperty();
private final ObjectProperty<GameStatistics> deckStatistics = new SimpleObjectProperty<>();
private final DoubleProperty winRate = new SimpleDoubleProperty();
public BattleDeckResult(String deckName, GameStatistics deckStatistics) {
setDeckName(deckName);
setDeckStatistics(deckStatistics);
setWinRate(deckStatistics.getDouble(Statistic.WIN_RATE));
}
public final StringProperty deckNameProperty() {
return this.deckName;
}
public final ObjectProperty<GameStatistics> deckStatisticsProperty() {
return this.deckStatistics;
}
public final String getDeckName() {
return this.deckNameProperty().get();
}
public final GameStatistics getDeckStatistics() {
return this.deckStatisticsProperty().get();
}
public final double getWinRate() {
return this.winRateProperty().get();
}
public final void setDeckName(final String deckName) {
this.deckNameProperty().set(deckName);
}
public final void setDeckStatistics(final GameStatistics deckStatistics) {
this.deckStatisticsProperty().set(deckStatistics);
}
public final void setWinRate(final double winRate) {
this.winRateProperty().set(winRate);
}
public final DoubleProperty winRateProperty() {
return this.winRate;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksConfigView.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.scene.layout.BorderPane;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.behaviour.IBehaviour;
import net.demilich.metastone.game.behaviour.PlayRandomBehaviour;
import net.demilich.metastone.game.behaviour.threat.GameStateValueBehaviour;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.DeckFormat;
import net.demilich.metastone.game.entities.heroes.HeroClass;
import net.demilich.metastone.gui.common.BehaviourStringConverter;
import net.demilich.metastone.gui.common.DeckStringConverter;
public class BattleOfDecksConfigView extends BorderPane {
@FXML
private ComboBox<Integer> numberOfGamesBox;
@FXML
private ComboBox<IBehaviour> behaviourBox;
@FXML
private ListView<Deck> selectedDecksListView;
@FXML
private ListView<Deck> availableDecksListView;
@FXML
private Button addButton;
@FXML
private Button removeButton;
@FXML
private Button startButton;
@FXML
private Button backButton;
public BattleOfDecksConfigView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/BattleOfDecksConfigView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
setupBehaviourBox();
setupNumberOfGamesBox();
selectedDecksListView.setCellFactory(TextFieldListCell.forListView(new DeckStringConverter()));
selectedDecksListView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
availableDecksListView.setCellFactory(TextFieldListCell.forListView(new DeckStringConverter()));
availableDecksListView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
addButton.setOnAction(this::handleAddButton);
removeButton.setOnAction(this::handleRemoveButton);
backButton.setOnAction(event -> NotificationProxy.sendNotification(GameNotification.MAIN_MENU));
startButton.setOnAction(this::handleStartButton);
}
private void handleAddButton(ActionEvent event) {
Collection<Deck> selectedDecks = availableDecksListView.getSelectionModel().getSelectedItems();
selectedDecksListView.getItems().addAll(selectedDecks);
availableDecksListView.getItems().removeAll(selectedDecks);
}
private void handleRemoveButton(ActionEvent event) {
Collection<Deck> selectedDecks = selectedDecksListView.getSelectionModel().getSelectedItems();
availableDecksListView.getItems().addAll(selectedDecks);
selectedDecksListView.getItems().removeAll(selectedDecks);
}
private void handleStartButton(ActionEvent event) {
int numberOfGames = numberOfGamesBox.getSelectionModel().getSelectedItem();
IBehaviour behaviour = behaviourBox.getSelectionModel().getSelectedItem();
Collection<Deck> decks = selectedDecksListView.getItems();
BattleConfig battleConfig = new BattleConfig(numberOfGames, behaviour, decks);
NotificationProxy.sendNotification(GameNotification.COMMIT_BATTLE_OF_DECKS_CONFIG, battleConfig);
}
public void injectDecks(List<Deck> decks) {
selectedDecksListView.getItems().clear();
ObservableList<Deck> validDecks = FXCollections.observableArrayList();
for (Deck deck : decks) {
if (deck.getHeroClass() == HeroClass.MAGE) {
continue;
}
}
availableDecksListView.getItems().setAll(validDecks);
}
private void setupBehaviourBox() {
behaviourBox.setConverter(new BehaviourStringConverter());
behaviourBox.getItems().setAll(new GameStateValueBehaviour(), new PlayRandomBehaviour());
behaviourBox.getSelectionModel().selectFirst();
}
private void setupNumberOfGamesBox() {
ObservableList<Integer> numberOfGamesEntries = FXCollections.observableArrayList();
numberOfGamesEntries.add(1);
numberOfGamesEntries.add(10);
numberOfGamesEntries.add(100);
numberOfGamesEntries.add(1000);
numberOfGamesBox.setItems(numberOfGamesEntries);
numberOfGamesBox.getSelectionModel().select(2);
}
public void injectDeckFormats(List<DeckFormat> deckFormats) {
// selectedDeckFormatsListView.getItems().clear();
// ObservableList<DeckFormat> validDeckFormats = FXCollections.observableArrayList();
// availableDeckFormatsListView.getItems().setAll(validDeckFormats);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksMediator.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import java.util.ArrayList;
import java.util.List;
import net.demilich.nittygrittymvc.Mediator;
import net.demilich.nittygrittymvc.interfaces.INotification;
import javafx.application.Platform;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.DeckFormat;
public class BattleOfDecksMediator extends Mediator<GameNotification> {
public final static String NAME = "BattleOfDecksMediator";
private final BattleOfDecksConfigView configView;
private final BattleOfDecksResultView resultView;
public BattleOfDecksMediator() {
super(NAME);
configView = new BattleOfDecksConfigView();
resultView = new BattleOfDecksResultView();
}
@SuppressWarnings("unchecked")
@Override
public void handleNotification(final INotification<GameNotification> notification) {
switch (notification.getId()) {
case REPLY_DECKS:
configView.injectDecks((List<Deck>) notification.getBody());
break;
case REPLY_DECK_FORMATS:
configView.injectDeckFormats((List<DeckFormat>) notification.getBody());
break;
case BATTLE_OF_DECKS_PROGRESS_UPDATE:
final BattleResult result = (BattleResult) notification.getBody();
Platform.runLater(() -> resultView.updateResults(result));
break;
case COMMIT_BATTLE_OF_DECKS_CONFIG:
sendNotification(GameNotification.SHOW_VIEW, resultView);
break;
default:
break;
}
}
@Override
public List<GameNotification> listNotificationInterests() {
List<GameNotification> notificationInterests = new ArrayList<GameNotification>();
notificationInterests.add(GameNotification.REPLY_DECKS);
notificationInterests.add(GameNotification.REPLY_DECK_FORMATS);
notificationInterests.add(GameNotification.BATTLE_OF_DECKS_PROGRESS_UPDATE);
notificationInterests.add(GameNotification.COMMIT_BATTLE_OF_DECKS_CONFIG);
return notificationInterests;
}
@Override
public void onRegister() {
sendNotification(GameNotification.SHOW_VIEW, configView);
sendNotification(GameNotification.REQUEST_DECKS);
sendNotification(GameNotification.REQUEST_DECK_FORMATS);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksResultView.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import java.io.IOException;
import java.util.HashMap;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.SortType;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.util.Callback;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
public class BattleOfDecksResultView extends BorderPane {
@FXML
private FlowPane batchResultPane;
@FXML
private TableView<BattleDeckResult> rankingTable;
@FXML
private Button backButton;
private final HashMap<BattleBatchResult, BattleBatchResultToken> tokenMap = new HashMap<>();
@SuppressWarnings("unchecked")
public BattleOfDecksResultView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/BattleOfDecksResultView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
TableColumn<BattleDeckResult, String> nameColumn = new TableColumn<>("Deck name");
nameColumn.setPrefWidth(200);
TableColumn<BattleDeckResult, Double> winRateColumn = new TableColumn<>("Win rate");
winRateColumn.setPrefWidth(150);
nameColumn.setCellValueFactory(new PropertyValueFactory<BattleDeckResult, String>("deckName"));
winRateColumn.setCellValueFactory(new PropertyValueFactory<BattleDeckResult, Double>("winRate"));
winRateColumn.setCellFactory(new Callback<TableColumn<BattleDeckResult, Double>, TableCell<BattleDeckResult, Double>>() {
public TableCell<BattleDeckResult, Double> call(TableColumn<BattleDeckResult, Double> p) {
TableCell<BattleDeckResult, Double> cell = new TableCell<BattleDeckResult, Double>() {
private final Label label = new Label();
private final ProgressBar progressBar = new ProgressBar();
private final StackPane stackPane = new StackPane();
{
label.getStyleClass().setAll("progress-text");
stackPane.setAlignment(Pos.CENTER);
stackPane.getChildren().setAll(progressBar, label);
setGraphic(stackPane);
}
@Override
protected void updateItem(Double winrate, boolean empty) {
super.updateItem(winrate, empty);
if (winrate == null || empty) {
setGraphic(null);
return;
}
progressBar.setProgress(winrate);
label.setText(String.format("%.2f", winrate * 100) + "%");
setGraphic(stackPane);
}
};
return cell;
}
});
rankingTable.getColumns().setAll(nameColumn, winRateColumn);
rankingTable.getColumns().get(1).setSortType(SortType.DESCENDING);
backButton.setOnAction(event -> NotificationProxy.sendNotification(GameNotification.MAIN_MENU));
}
@SuppressWarnings("unchecked")
public void updateResults(BattleResult result) {
for (BattleBatchResult batchResult : result.getBatchResults()) {
if (!tokenMap.containsKey(batchResult)) {
BattleBatchResultToken token = new BattleBatchResultToken();
tokenMap.put(batchResult, token);
batchResultPane.getChildren().add(token);
}
BattleBatchResultToken batchResultToken = tokenMap.get(batchResult);
batchResultToken.displayBatchResult(batchResult);
}
rankingTable.getItems().setAll(result.getDeckResults());
rankingTable.getSortOrder().setAll(rankingTable.getColumns().get(1));
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleResult.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.Player;
import net.demilich.metastone.game.statistics.GameStatistics;
public class BattleResult {
private final int numberOfGames;
private final HashMap<String, GameStatistics> deckResults = new HashMap<String, GameStatistics>();
private final List<BattleBatchResult> batchResults = new ArrayList<BattleBatchResult>();
public BattleResult(int numberOfGames) {
this.numberOfGames = numberOfGames;
}
public void addBatchResult(BattleBatchResult batchResult) {
synchronized (batchResults) {
batchResults.add(batchResult);
}
}
public List<BattleBatchResult> getBatchResults() {
synchronized (batchResults) {
return new ArrayList<BattleBatchResult>(batchResults);
}
}
public List<BattleDeckResult> getDeckResults() {
List<BattleDeckResult> resultList = new ArrayList<BattleDeckResult>();
synchronized (deckResults) {
for (String deckName : deckResults.keySet()) {
BattleDeckResult deckResult = new BattleDeckResult(deckName, deckResults.get(deckName));
resultList.add(deckResult);
}
}
return resultList;
}
public int getNumberOfGames() {
return numberOfGames;
}
public void onGameEnded(GameContext result) {
for (Player player : result.getPlayers()) {
updateStats(player);
}
}
private void updateStats(Player player) {
String deckName = player.getDeckName();
synchronized (deckResults) {
if (!deckResults.containsKey(deckName)) {
deckResults.put(deckName, new GameStatistics());
}
GameStatistics stats = deckResults.get(deckName);
stats.merge(player.getStatistics());
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/StartBattleOfDecksCommand.java
================================================
package net.demilich.metastone.gui.battleofdecks;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.Player;
import net.demilich.metastone.game.behaviour.IBehaviour;
import net.demilich.metastone.game.cards.CardSet;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.DeckFormat;
import net.demilich.metastone.game.logic.GameLogic;
import net.demilich.metastone.game.gameconfig.PlayerConfig;
public class StartBattleOfDecksCommand extends SimpleCommand<GameNotification> {
private class PlayGameTask implements Callable<Void> {
private final PlayerConfig player1Config;
private final PlayerConfig player2Config;
private final BattleBatchResult batchResult;
public PlayGameTask(Deck deck1, Deck deck2, IBehaviour behaviour, BattleBatchResult batchResult) {
this.player1Config = new PlayerConfig(deck1, behaviour);
player1Config.setName("Player 1");
this.player2Config = new PlayerConfig(deck2, behaviour);
player2Config.setName("Player 2");
this.batchResult = batchResult;
}
@Override
public Void call() throws Exception {
Player player1 = new Player(player1Config);
Player player2 = new Player(player2Config);
DeckFormat deckFormat = new DeckFormat();
for (CardSet set : CardSet.values()) {
deckFormat.addSet(set);
}
GameContext newGame = new GameContext(player1, player2, new GameLogic(), deckFormat);
newGame.play();
batchResult.onGameEnded(newGame);
result.onGameEnded(newGame);
periodicUpdate();
newGame.dispose();
return null;
}
}
private static Logger logger = LoggerFactory.getLogger(StartBattleOfDecksCommand.class);
private BattleResult result;
private long lastUpdate;
@Override
public void execute(INotification<GameNotification> notification) {
BattleConfig battleConfig = (BattleConfig) notification.getBody();
result = new BattleResult(battleConfig.getNumberOfGames());
Thread t = new Thread(new Runnable() {
@Override
public void run() {
logger.info("Battle of Decks started");
ExecutorService executor = Executors.newWorkStealingPool();
List<Future<Void>> futures = new ArrayList<Future<Void>>();
HashSet<Deck> processedDecks = new HashSet<>();
for (Deck deck1 : battleConfig.getDecks()) {
processedDecks.add(deck1);
for (Deck deck2 : battleConfig.getDecks()) {
if (processedDecks.contains(deck2)) {
continue;
}
BattleBatchResult batchResult = new BattleBatchResult(deck1, deck2, battleConfig.getNumberOfGames());
result.addBatchResult(batchResult);
for (int i = 0; i < battleConfig.getNumberOfGames(); i++) {
PlayGameTask task = new PlayGameTask(deck1, deck2, battleConfig.getBehaviour(), batchResult);
Future<Void> future = executor.submit(task);
futures.add(future);
}
}
}
executor.shutdown();
boolean completed = false;
while (!completed) {
completed = true;
for (Future<Void> future : futures) {
if (!future.isDone()) {
completed = false;
continue;
}
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
logger.error(ExceptionUtils.getStackTrace(e));
e.printStackTrace();
System.exit(-1);
}
}
futures.removeIf(future -> future.isDone());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// getFacade().sendNotification(GameNotification.SIMULATION_RESULT,
// result);
logger.info("Battle of Decks finished");
}
});
t.setDaemon(true);
t.start();
}
private void periodicUpdate() {
if (System.currentTimeMillis() - lastUpdate > 1000) {
sendNotification(GameNotification.BATTLE_OF_DECKS_PROGRESS_UPDATE, result);
lastUpdate = System.currentTimeMillis();
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/cards/CardProxy.java
================================================
package net.demilich.metastone.gui.cards;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.cards.CardCatalogue;
import net.demilich.metastone.game.cards.CardParseException;
import net.demilich.nittygrittymvc.Proxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class CardProxy extends Proxy<GameNotification> {
public final static String NAME = "CardProxy";
private static Logger logger = LoggerFactory.getLogger(CardProxy.class);
public CardProxy() {
super(NAME);
try {
// ensure user's personal cards dir exists
Files.createDirectories(Paths.get(CardCatalogue.CARDS_FOLDER_PATH));
// ensure cards have been copied to ~/metastone/cards
CardCatalogue.copyCardsFromResources();
CardCatalogue.loadCards();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
logger.error("Trouble creating " + Paths.get(CardCatalogue.CARDS_FOLDER_PATH));
e.printStackTrace();
} catch (CardParseException cpe) {
getFacade().sendNotification(GameNotification.CARD_PARSE_ERROR, cpe.getMessage());
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/cards/CardToken.java
================================================
package net.demilich.metastone.gui.cards;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.Player;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardType;
import net.demilich.metastone.game.cards.MinionCard;
import net.demilich.metastone.game.cards.Rarity;
import net.demilich.metastone.game.cards.WeaponCard;
import net.demilich.metastone.gui.DigitFactory;
import net.demilich.metastone.gui.IconFactory;
public class CardToken extends BorderPane {
@FXML
protected Group manaCostAnchor;
@FXML
protected Label nameLabel;
@FXML
protected Label descriptionLabel;
@FXML
protected Group attackAnchor;
@FXML
protected Group hpAnchor;
@FXML
protected ImageView attackIcon;
@FXML
protected ImageView hpIcon;
@FXML
protected Circle rarityGem;
private double baseRarityGemSize;
protected Card card;
protected CardToken(String fxml) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/" + fxml));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
baseRarityGemSize = rarityGem.getRadius();
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
setCard(null, card, null);
}
public void setCard(GameContext context, Card card, Player player) {
this.card = card;
nameLabel.setText(card.getName());
setRarity(card.getRarity());
if (context != null || player != null) {
int modifiedManaCost = context.getLogic().getModifiedManaCost(player, card);
setScoreValueLowerIsBetter(manaCostAnchor, modifiedManaCost, card.getBaseManaCost());
} else {
setScoreValue(manaCostAnchor, card.getBaseManaCost());
}
boolean isMinionOrWeaponCard = card.getCardType().isCardType(CardType.MINION) || card.getCardType().isCardType(CardType.WEAPON);
attackAnchor.setVisible(isMinionOrWeaponCard);
hpAnchor.setVisible(isMinionOrWeaponCard);
attackIcon.setVisible(isMinionOrWeaponCard);
hpIcon.setVisible(isMinionOrWeaponCard);
if (card.getCardType().isCardType(CardType.MINION)) {
MinionCard minionCard = (MinionCard) card;
setScoreValue(attackAnchor, minionCard.getAttack() + minionCard.getBonusAttack(), minionCard.getBaseAttack());
setScoreValue(hpAnchor, minionCard.getHp() + minionCard.getBonusHp(), minionCard.getBaseHp());
} else if (card.getCardType().isCardType(CardType.WEAPON)) {
WeaponCard weaponCard = (WeaponCard) card;
setScoreValue(attackAnchor, weaponCard.getDamage() + weaponCard.getBonusDamage(), weaponCard.getBaseDamage());
setScoreValue(hpAnchor, weaponCard.getDurability() + weaponCard.getBonusDurability(), weaponCard.getBaseDurability());
}
}
public void setNonCard(String name, String description) {
nameLabel.setText(name);
descriptionLabel.setText(description);
setRarity(Rarity.FREE);
manaCostAnchor.setVisible(false);
attackAnchor.setVisible(false);
hpAnchor.setVisible(false);
attackIcon.setVisible(false);
hpIcon.setVisible(false);
}
private void setRarity(Rarity rarity) {
rarityGem.setFill(IconFactory.getRarityColor(rarity));
rarityGem.setVisible(rarity != Rarity.FREE);
rarityGem.setRadius(rarity == Rarity.LEGENDARY ? baseRarityGemSize * 1.5 : baseRarityGemSize);
}
protected void setScoreValue(Group group, int value) {
setScoreValue(group, value, value);
}
protected void setScoreValue(Group group, int value, int baseValue) {
Color color = Color.WHITE;
if (value > baseValue) {
color = Color.GREEN;
}
DigitFactory.showPreRenderedDigits(group, value, color);
}
protected void setScoreValue(Group group, int value, int baseValue, int maxValue) {
Color color = Color.WHITE;
if (value < maxValue) {
color = Color.RED;
} else if (value > baseValue) {
color = Color.GREEN;
}
DigitFactory.showPreRenderedDigits(group, value, color);
}
private void setScoreValueLowerIsBetter(Group group, int value, int baseValue) {
Color color = Color.WHITE;
if (value < baseValue) {
color = Color.GREEN;
} else if (value > baseValue) {
color = Color.RED;
}
DigitFactory.showPreRenderedDigits(group, value, color);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/cards/CardTokenFactory.java
================================================
package net.demilich.metastone.gui.cards;
import java.util.ArrayList;
import java.util.List;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.Player;
import net.demilich.metastone.game.cards.Card;
public class CardTokenFactory {
private static final int HAND_CARDS = 10;
private List<HandCard> cachedHandCards = new ArrayList<HandCard>(HAND_CARDS);
public CardTokenFactory() {
for (int i = 0; i < HAND_CARDS; i++) {
cachedHandCards.add(new HandCard());
}
}
public CardToken createHandCard(GameContext context, Card card, Player player) {
HandCard handCard = getHandCard();
handCard.setCard(context, card, player);
return handCard;
}
private HandCard getHandCard() {
for (HandCard handCard : cachedHandCards) {
if (handCard.getParent() == null) {
return handCard;
}
}
return new HandCard();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/cards/CardTooltip.java
================================================
package net.demilich.metastone.gui.cards;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import net.demilich.metastone.game.Attribute;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.Player;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.entities.minions.Race;
public class CardTooltip extends CardToken {
@FXML
private Label raceLabel;
public CardTooltip() {
super("CardTooltip.fxml");
}
@Override
public void setCard(GameContext context, Card card, Player player) {
super.setCard(context, card, player);
descriptionLabel.setText(card.getDescription());
if (!card.hasAttribute(Attribute.RACE) || card.getAttribute(Attribute.RACE) == Race.NONE) {
raceLabel.setVisible(false);
} else {
raceLabel.setText(card.getAttribute(Attribute.RACE).toString());
raceLabel.setVisible(true);
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/cards/HandCard.java
================================================
package net.demilich.metastone.gui.cards;
import javafx.fxml.FXML;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundImage;
import javafx.scene.layout.BackgroundPosition;
import javafx.scene.layout.BackgroundRepeat;
import javafx.scene.layout.BackgroundSize;
import javafx.scene.layout.Pane;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.Player;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.gui.IconFactory;
public class HandCard extends CardToken {
@FXML
private Pane topPane;
@FXML
private Pane centerPane;
@FXML
private Pane bottomPane;
private CardTooltip tooltipContent;
private Tooltip tooltip;
public HandCard() {
super("HandCard.fxml");
hideCard(true);
}
private void hideCard(boolean hide) {
topPane.setVisible(!hide);
centerPane.setVisible(!hide);
bottomPane.setVisible(!hide);
if (hide) {
BackgroundSize size = new BackgroundSize(getWidth(), getHeight(), false, false, true, false);
BackgroundImage image = new BackgroundImage(IconFactory.getDefaultCardBack(), BackgroundRepeat.NO_REPEAT,
BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, size);
Background background = new Background(image);
setBackground(background);
}
}
@Override
public void setCard(GameContext context, Card card, Player player) {
super.setCard(context, card, player);
if (tooltipContent == null) {
tooltip = new Tooltip();
tooltipContent = new CardTooltip();
tooltipContent.setCard(context, card, player);
tooltip.setGraphic(tooltipContent);
Tooltip.install(this, tooltip);
} else {
tooltipContent.setCard(context, card, player);
}
hideCard(player.hideCards());
if (player.hideCards()) {
Tooltip.uninstall(this, tooltip);
tooltipContent = null;
tooltip = null;
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/common/BehaviourStringConverter.java
================================================
package net.demilich.metastone.gui.common;
import javafx.util.StringConverter;
import net.demilich.metastone.game.behaviour.IBehaviour;
public class BehaviourStringConverter extends StringConverter<IBehaviour> {
@Override
public IBehaviour fromString(String string) {
return null;
}
@Override
public String toString(IBehaviour behaviour) {
return behaviour.getName();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/common/CardSetStringConverter.java
================================================
package net.demilich.metastone.gui.common;
import javafx.util.StringConverter;
import net.demilich.metastone.game.cards.CardSet;
public class CardSetStringConverter extends StringConverter<CardSet> {
@Override
public CardSet fromString(String string) {
return null;
}
@Override
public String toString(CardSet object) {
return object.toString();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/common/ComboBoxKeyHandler.java
================================================
package net.demilich.metastone.gui.common;
import com.sun.javafx.scene.control.skin.ComboBoxListViewSkin;
import javafx.event.EventHandler;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
public class ComboBoxKeyHandler<T> implements EventHandler<KeyEvent> {
private static final long WORD_DELAY = 2000;
private String s;
private final ComboBox<T> box;
private long lastKeyPress;
public ComboBoxKeyHandler(ComboBox<T> box) {
this.box = box;
s = "";
}
@Override
public void handle(KeyEvent event) {
if (System.currentTimeMillis() - WORD_DELAY > lastKeyPress) {
s = "";
}
// handle non alphanumeric keys like backspace, delete etc
if (event.getCode() == KeyCode.BACK_SPACE && s.length() > 0)
s = s.substring(0, s.length() - 1);
else
s += event.getText();
lastKeyPress = System.currentTimeMillis();
if (s.length() == 0) {
select(0);
return;
}
for (T item : box.getItems()) {
String name = box.getConverter().toString(item).toLowerCase();
if (name.startsWith(s)) {
select(item);
return;
}
}
// nothing found, reset search string
s = "";
}
private void select(int index) {
select(box.getItems().get(index));
}
@SuppressWarnings("rawtypes")
private void select(T item) {
box.getSelectionModel().select(item);
ListView lv = ((ComboBoxListViewSkin) box.getSkin()).getListView();
lv.scrollTo(lv.getSelectionModel().getSelectedIndex());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/common/DeckFormatStringConverter.java
================================================
package net.demilich.metastone.gui.common;
import javafx.util.StringConverter;
import net.demilich.metastone.game.decks.DeckFormat;
public class DeckFormatStringConverter extends StringConverter<DeckFormat> {
@Override
public DeckFormat fromString(String arg0) {
return null;
}
@Override
public String toString(DeckFormat format) {
return format.getName();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/common/DeckStringConverter.java
================================================
package net.demilich.metastone.gui.common;
import javafx.util.StringConverter;
import net.demilich.metastone.game.decks.Deck;
public class DeckStringConverter extends StringConverter<Deck> {
@Override
public Deck fromString(String arg0) {
return null;
}
@Override
public String toString(Deck deck) {
return deck.getName();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/common/HeroStringConverter.java
================================================
package net.demilich.metastone.gui.common;
import javafx.util.StringConverter;
import net.demilich.metastone.game.cards.HeroCard;
public class HeroStringConverter extends StringConverter<HeroCard> {
@Override
public HeroCard fromString(String arg0) {
return null;
}
@Override
public String toString(HeroCard hero) {
return hero.getHeroClass().toString();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/common/IntegerTextField.java
================================================
package net.demilich.metastone.gui.common;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
public class IntegerTextField extends RestrictedTextField {
private final IntegerProperty valueProperty = new SimpleIntegerProperty();
public IntegerTextField(int maxLength) {
setRestrict("\\d*");
setMaxLength(maxLength);
}
public int getIntValue() {
return valueProperty().get();
}
public void setIntValue(int value) {
setText(String.valueOf(value));
}
@Override
protected void validInput(String validInput) {
valueProperty().set(validInput.length() > 0 ? Integer.parseInt(validInput) : 0);
if (validInput.length() == 0) {
setIntValue(0);
}
}
public IntegerProperty valueProperty() {
return valueProperty;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/common/RestrictedTextField.java
================================================
package net.demilich.metastone.gui.common;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;
/**
* A text field, which restricts the user's input.
*
* @author Christian Schudt
*/
public class RestrictedTextField extends TextField {
private StringProperty restrict = new SimpleStringProperty();
private IntegerProperty maxLength = new SimpleIntegerProperty(-1);
public RestrictedTextField() {
textProperty().addListener(new ChangeListener<String>() {
private boolean ignore;
@Override
public void changed(ObservableValue<? extends String> observableValue, String s, String s1) {
if (ignore)
return;
if (maxLength.get() > -1 && s1.length() > maxLength.get()) {
ignore = true;
setText(s1.substring(0, maxLength.get()));
validInput(getText());
ignore = false;
return;
}
if (restrict.get() != null && !restrict.get().equals("") && !s1.matches(restrict.get())) {
ignore = true;
setText(s);
ignore = false;
return;
}
validInput(getText());
}
});
}
public int getMaxLength() {
return maxLength.get();
}
public String getRestrict() {
return restrict.get();
}
public IntegerProperty maxLengthProperty() {
return maxLength;
}
public StringProperty restrictProperty() {
return restrict;
}
/**
* Sets the max length of the text field.
*
* @param maxLength
* The max length.
*/
public void setMaxLength(int maxLength) {
this.maxLength.set(maxLength);
}
/**
* Sets a regular expression character class which restricts the user input.
* <br/>
* E.g. [0-9] only allows numeric values.
*
* @param restrict
* The regular expression.
*/
public void setRestrict(String restrict) {
this.restrict.set(restrict);
}
protected void validInput(String validInput) {
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/AddCardToDeckCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.cards.Card;
public class AddCardToDeckCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
Card card = (Card) notification.getBody();
if (deckProxy.addCardToDeck(card)) {
getFacade().sendNotification(GameNotification.ACTIVE_DECK_CHANGED, deckProxy.getActiveDeck());
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardEntry.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import net.demilich.metastone.game.cards.Card;
public class CardEntry extends HBox {
@FXML
private Label cardNameLabel;
@FXML
private Text manaCostText;
@FXML
private Text countText;
private int stack;
private Card card;
public CardEntry() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/CardEntry.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
setCache(true);
}
public void addCard(Card card) {
this.card = card;
cardNameLabel.setText(card.getName());
manaCostText.setText(String.valueOf(card.getBaseManaCost()));
stack++;
countText.setText(String.valueOf(stack));
countText.setVisible(stack > 1);
}
public Card getCard() {
return card;
}
public void resetStackCount() {
stack = 0;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardEntryFactory.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.util.ArrayList;
import java.util.List;
import net.demilich.metastone.game.cards.Card;
public class CardEntryFactory {
private static final int CARD_ENTRIES = 10;
private List<CardEntry> cachedCardEntries = new ArrayList<CardEntry>(CARD_ENTRIES);
public CardEntryFactory() {
for (int i = 0; i < CARD_ENTRIES; i++) {
cachedCardEntries.add(new CardEntry());
}
}
public CardEntry createCardEntry(Card card) {
CardEntry cardEntry = getCardEntry();
cardEntry.resetStackCount();
cardEntry.addCard(card);
return cardEntry;
}
private CardEntry getCardEntry() {
for (CardEntry handCard : cachedCardEntries) {
if (handCard.getParent() == null) {
return handCard;
}
}
return new CardEntry();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardFilter.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import net.demilich.metastone.game.cards.CardSet;
import net.demilich.metastone.game.decks.DeckFormat;
public class CardFilter {
private final String text;
private final CardSet set;
private final DeckFormat format;
public CardFilter(String text, CardSet set, DeckFormat format) {
this.text = text;
this.set = set;
this.format = format;
}
public DeckFormat getFormat() {
return format;
}
public CardSet getSet() {
return set;
}
public String getText() {
return text;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardFilterView.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.cards.CardSet;
import net.demilich.metastone.game.decks.DeckFormat;
import net.demilich.metastone.gui.common.CardSetStringConverter;
import net.demilich.metastone.gui.common.DeckFormatStringConverter;
public class CardFilterView extends HBox {
@FXML
private TextField searchField;
@FXML
private ComboBox<CardSet> cardSetBox;
@FXML
private ComboBox<DeckFormat> deckFormatBox;
private List<DeckFormat> deckFormats = new ArrayList<DeckFormat>();
public CardFilterView(List<DeckFormat> deckFormats) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/CardFilterView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
searchField.textProperty().addListener(this::textChanged);
deckFormatBox.setConverter(new DeckFormatStringConverter());
DeckFormat deckFormat = new DeckFormat();
deckFormat.setName("DECK FORMAT");
deckFormats.add(0, deckFormat);
deckFormatBox.setItems(FXCollections.observableArrayList(deckFormats));
deckFormatBox.getSelectionModel().selectFirst();
deckFormatBox.valueProperty().addListener(this::formatChanged);
cardSetBox.setConverter(new CardSetStringConverter());
cardSetBox.setItems(FXCollections.observableArrayList(CardSet.values()));
cardSetBox.getSelectionModel().selectFirst();
cardSetBox.valueProperty().addListener(this::setChanged);
}
private void filterChanged() {
DeckFormat deckFormat = null;
if (!deckFormatBox.getSelectionModel().isSelected(0)) {
deckFormat = deckFormatBox.getSelectionModel().getSelectedItem();
}
NotificationProxy.sendNotification(GameNotification.FILTER_CARDS,
new CardFilter(searchField.getText(), cardSetBox.getSelectionModel().getSelectedItem(), deckFormat));
}
private void formatChanged(ObservableValue<? extends DeckFormat> observable, DeckFormat oldValue, DeckFormat newValue) {
CardSet set = cardSetBox.getSelectionModel().getSelectedItem();
if (deckFormatBox.getSelectionModel().isSelected(0)) {
cardSetBox.setItems(FXCollections.observableArrayList(CardSet.values()));
} else {
List<CardSet> sets = newValue.getCardSets();
sets.add(0, CardSet.ANY);
cardSetBox.setItems(FXCollections.observableArrayList(sets));
}
if (!deckFormatBox.getSelectionModel().isSelected(0) && !set.equals(CardSet.ANY) && !newValue.isInFormat(set)) {
cardSetBox.getSelectionModel().selectFirst();
} else {
cardSetBox.getSelectionModel().select(set);
}
filterChanged();
}
public void injectDeckFormats(List<DeckFormat> deckFormats) {
this.deckFormats.addAll(deckFormats);
}
private void setChanged(ObservableValue<? extends CardSet> observable, CardSet oldValue, CardSet newValue) {
filterChanged();
}
private void textChanged(ObservableValue<? extends String> observable, String oldValue, String newValue) {
filterChanged();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardListView.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.util.HashMap;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.decks.Deck;
public class CardListView extends VBox implements EventHandler<MouseEvent> {
private final HashMap<String, CardEntry> existingCardEntries = new HashMap<String, CardEntry>();
private final CardEntryFactory cardEntryFactory = new CardEntryFactory();
public CardListView() {
super(2);
this.setAlignment(Pos.TOP_LEFT);
this.setPrefSize(240, USE_COMPUTED_SIZE);
}
private void clearChildren() {
for (Node child : getChildren()) {
child.removeEventHandler(MouseEvent.MOUSE_CLICKED, this);
}
getChildren().clear();
}
public void displayDeck(Deck deck) {
existingCardEntries.clear();
clearChildren();
for (Card card : deck.getCards()) {
String cardId = card.getCardId();
CardEntry cardEntry = null;
if (existingCardEntries.containsKey(cardId)) {
cardEntry = existingCardEntries.get(cardId);
cardEntry.addCard(card);
} else {
cardEntry = cardEntryFactory.createCardEntry(card);
cardEntry.addEventHandler(MouseEvent.MOUSE_CLICKED, this);
getChildren().add(cardEntry);
existingCardEntries.put(cardId, cardEntry);
}
}
}
@Override
public void handle(MouseEvent event) {
Card card = null;
for (CardEntry cardEntry : existingCardEntries.values()) {
if (event.getSource() == cardEntry) {
card = cardEntry.getCard();
break;
}
}
if (card != null) {
NotificationProxy.sendNotification(GameNotification.REMOVE_CARD_FROM_DECK, card);
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardView.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.gui.cards.CardTooltip;
public class CardView extends BorderPane implements EventHandler<MouseEvent> {
@FXML
private Pane contentPane;
@FXML
private Button previousButton;
@FXML
private Button nextButton;
@FXML
private Label pageLabel;
private int offset;
private final int rows = 4;
private final int columns = 2;
private final int cardDisplayCount = rows * columns;
private List<Card> cards;
private final List<CardTooltip> cardWidgets = new ArrayList<CardTooltip>(cardDisplayCount);
public CardView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/CardView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
setupCardWidgets();
previousButton.setOnAction(actionEvent -> changeOffset(-cardDisplayCount));
nextButton.setOnAction(actionEvent -> changeOffset(+cardDisplayCount));
setCache(true);
}
private void changeOffset(int delta) {
int newOffset = offset + delta;
if (newOffset < 0 || newOffset >= cards.size()) {
return;
}
offset += delta;
displayCurrentPage();
}
public void displayCards(List<Card> cards) {
this.cards = cards;
offset = 0;
displayCurrentPage();
}
private void displayCurrentPage() {
int lastIndex = Math.min(cards.size(), offset + cardDisplayCount);
updatePageLabel();
for (CardTooltip CardTooltip : cardWidgets) {
CardTooltip.setVisible(false);
}
int widgetIndex = 0;
for (int i = offset; i < lastIndex; i++) {
Card card = cards.get(i);
CardTooltip cardWidget = cardWidgets.get(widgetIndex++);
cardWidget.setCard(card);
cardWidget.setVisible(true);
}
}
@Override
public void handle(MouseEvent event) {
CardTooltip source = (CardTooltip) event.getSource();
Card card = source.getCard();
NotificationProxy.sendNotification(GameNotification.ADD_CARD_TO_DECK, card);
}
private void setupCardWidgets() {
for (int i = 0; i < cardDisplayCount; i++) {
CardTooltip cardWidget = new CardTooltip();
cardWidget.addEventHandler(MouseEvent.MOUSE_CLICKED, this);
cardWidget.setScaleX(0.95);
cardWidget.setScaleY(0.95);
cardWidget.setScaleZ(0.95);
contentPane.getChildren().add(cardWidget);
cardWidgets.add(cardWidget);
}
}
private void updatePageLabel() {
int totalPages = (int) Math.ceil(cards.size() / (double) cardDisplayCount);
int currentPage = (int) Math.ceil(offset / (double) cardDisplayCount) + 1;
pageLabel.setText(currentPage + "/" + totalPages);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/ChangeDeckNameCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
public class ChangeDeckNameCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
String newDeckName = (String) notification.getBody();
deckProxy.getActiveDeck().setName(newDeckName);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/ChooseClassView.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.IOException;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.BorderPane;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.MetaDeck;
import net.demilich.metastone.game.entities.heroes.HeroClass;
public class ChooseClassView extends BorderPane implements EventHandler<ActionEvent> {
@FXML
private Button warriorButton;
@FXML
private Button paladinButton;
@FXML
private Button druidButton;
@FXML
private Button rogueButton;
@FXML
private Button warlockButton;
@FXML
private Button hunterButton;
@FXML
private Button shamanButton;
@FXML
private Button mageButton;
@FXML
private Button priestButton;
@FXML
private Button collectionButton;
@FXML
private CheckBox arbitraryCheckBox;
private boolean arbitrary;
public ChooseClassView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/ChooseClassView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
arbitrary = false;
setupArbitraryBox();
warriorButton.setOnAction(this);
paladinButton.setOnAction(this);
druidButton.setOnAction(this);
rogueButton.setOnAction(this);
warlockButton.setOnAction(this);
hunterButton.setOnAction(this);
shamanButton.setOnAction(this);
mageButton.setOnAction(this);
priestButton.setOnAction(this);
collectionButton.setOnAction(this);
}
@Override
public void handle(ActionEvent event) {
Deck newDeck = null;
if (event.getSource() == warriorButton) {
newDeck = new Deck(HeroClass.WARRIOR, arbitrary);
} else if (event.getSource() == paladinButton) {
newDeck = new Deck(HeroClass.PALADIN, arbitrary);
} else if (event.getSource() == druidButton) {
newDeck = new Deck(HeroClass.DRUID, arbitrary);
} else if (event.getSource() == rogueButton) {
newDeck = new Deck(HeroClass.ROGUE, arbitrary);
} else if (event.getSource() == warlockButton) {
newDeck = new Deck(HeroClass.WARLOCK, arbitrary);
} else if (event.getSource() == hunterButton) {
newDeck = new Deck(HeroClass.HUNTER, arbitrary);
} else if (event.getSource() == shamanButton) {
newDeck = new Deck(HeroClass.SHAMAN, arbitrary);
} else if (event.getSource() == mageButton) {
newDeck = new Deck(HeroClass.MAGE, arbitrary);
} else if (event.getSource() == priestButton) {
newDeck = new Deck(HeroClass.PRIEST, arbitrary);
} else if (event.getSource() == collectionButton) {
newDeck = new MetaDeck();
}
NotificationProxy.sendNotification(GameNotification.SET_ACTIVE_DECK, newDeck);
}
private void onArbitraryBoxChanged(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) {
arbitrary = newValue;
// deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
// deckProxy.setActiveDeckValidator(new ArbitraryDeckValidator());
}
private void setupArbitraryBox() {
arbitraryCheckBox.selectedProperty().addListener(this::onArbitraryBoxChanged);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckBuilderMediator.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.util.ArrayList;
import java.util.List;
import net.demilich.nittygrittymvc.Mediator;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.DeckFormat;
import net.demilich.metastone.game.decks.validation.DefaultDeckValidator;
import net.demilich.metastone.gui.dialog.DialogNotification;
import net.demilich.metastone.gui.dialog.DialogType;
public class DeckBuilderMediator extends Mediator<GameNotification> {
public static final String NAME = "DeckBuilderMediator";
private final DeckBuilderView view;
public DeckBuilderMediator() {
super(NAME);
view = new DeckBuilderView();
}
@SuppressWarnings("unchecked")
@Override
public void handleNotification(final INotification<GameNotification> notification) {
switch (notification.getId()) {
case CREATE_NEW_DECK:
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
deckProxy.setActiveDeckValidator(new DefaultDeckValidator());
view.createNewDeck();
break;
case EDIT_DECK:
view.editDeck((Deck) notification.getBody());
break;
case ACTIVE_DECK_CHANGED:
view.activeDeckChanged((Deck) notification.getBody());
break;
case FILTERED_CARDS:
view.filteredCards((List<Card>) notification.getBody());
break;
case DECKS_LOADED:
view.displayDecks((List<Deck>) notification.getBody());
break;
case INVALID_DECK_NAME:
DialogNotification dialogNotification = new DialogNotification("Name your deck", "Please enter a valid name for this deck.",
DialogType.WARNING);
getFacade().notifyObservers(dialogNotification);
break;
case DECK_FORMATS_LOADED:
List<DeckFormat> deckFormats = (List<DeckFormat>) notification.getBody();
view.injectDeckFormats(deckFormats);
break;
case DUPLICATE_DECK_NAME:
getFacade().notifyObservers(new DialogNotification("Duplicate deck name",
"This deck name was already used for another deck. Please choose another name", DialogType.WARNING));
break;
default:
break;
}
}
@Override
public List<GameNotification> listNotificationInterests() {
List<GameNotification> notificationInterests = new ArrayList<GameNotification>();
notificationInterests.add(GameNotification.CREATE_NEW_DECK);
notificationInterests.add(GameNotification.EDIT_DECK);
notificationInterests.add(GameNotification.FILTERED_CARDS);
notificationInterests.add(GameNotification.ACTIVE_DECK_CHANGED);
notificationInterests.add(GameNotification.DECKS_LOADED);
notificationInterests.add(GameNotification.DECK_FORMATS_LOADED);
notificationInterests.add(GameNotification.INVALID_DECK_NAME);
notificationInterests.add(GameNotification.DUPLICATE_DECK_NAME);
return notificationInterests;
}
@Override
public void onRegister() {
getFacade().sendNotification(GameNotification.SHOW_VIEW, view);
getFacade().sendNotification(GameNotification.LOAD_DECKS);
getFacade().sendNotification(GameNotification.LOAD_DECK_FORMATS);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckBuilderView.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.DeckFormat;
import net.demilich.metastone.game.decks.MetaDeck;
import net.demilich.metastone.gui.deckbuilder.metadeck.MetaDeckListView;
import net.demilich.metastone.gui.deckbuilder.metadeck.MetaDeckView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class DeckBuilderView extends BorderPane implements EventHandler<ActionEvent> {
@FXML
private ScrollPane scrollPane;
@FXML
private Pane lowerInfoArea;
@FXML
private Pane upperInfoArea;
@FXML
private TextField importField;
@FXML
private Button importButton;
@FXML
private Button backButton;
private final CardView cardView;
private final CardListView cardListView;
private final DeckInfoView deckInfoView;
private final DeckListView deckListView;
private final DeckNameView deckNameView;
private final MetaDeckView metaDeckView;
private final MetaDeckListView metaDeckListView;
private List<DeckFormat> deckFormats = new ArrayList<DeckFormat>();
public DeckBuilderView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/DeckBuilderView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
importButton.setOnAction(this);
backButton.setOnAction(this);
cardView = new CardView();
cardListView = new CardListView();
deckInfoView = new DeckInfoView();
deckListView = new DeckListView();
deckNameView = new DeckNameView();
metaDeckView = new MetaDeckView();
metaDeckListView = new MetaDeckListView();
showSidebar(deckListView);
}
public void activeDeckChanged(Deck activeDeck) {
if (activeDeck.isMetaDeck()) {
MetaDeck metaDeck = (MetaDeck) activeDeck;
metaDeckListView.displayDecks(metaDeck.getDecks());
metaDeckView.deckChanged(metaDeck);
} else {
activeDeck.getCards().sortByManaCost();
cardListView.displayDeck(activeDeck);
}
deckInfoView.updateDeck(activeDeck);
deckNameView.updateDeck(activeDeck);
}
public void createNewDeck() {
showMainArea(new ChooseClassView());
showSidebar(null);
}
public void displayDecks(List<Deck> decks) {
deckListView.displayDecks(decks);
metaDeckView.displayDecks(decks);
}
public void editDeck(Deck deck) {
if (deck.isMetaDeck()) {
showMainArea(metaDeckView);
showSidebar(metaDeckListView);
} else {
showMainArea(cardView);
showSidebar(cardListView);
showBottomBar(new CardFilterView(deckFormats));
}
showLowerInfoArea(deckInfoView);
showUpperInfoArea(deckNameView);
}
public void filteredCards(List<Card> filteredCards) {
cardView.displayCards(filteredCards);
}
@Override
public void handle(ActionEvent event) {
if (event.getSource() == importButton) {
NotificationProxy.sendNotification(GameNotification.IMPORT_DECK_FROM_URL, importField.getText());
} else if (event.getSource() == backButton) {
NotificationProxy.sendNotification(GameNotification.MAIN_MENU);
}
}
public void injectDeckFormats(List<DeckFormat> deckFormats) {
this.deckFormats.addAll(deckFormats);
}
private void showBottomBar(Node content) {
BorderPane.setAlignment(content, Pos.CENTER);
setBottom(content);
}
private void showLowerInfoArea(Node content) {
lowerInfoArea.getChildren().clear();
lowerInfoArea.getChildren().add(content);
}
private void showMainArea(Node content) {
setCenter(content);
}
private void showSidebar(Node content) {
scrollPane.setVisible(content != null);
scrollPane.setContent(content);
}
private void showUpperInfoArea(Node content) {
upperInfoArea.getChildren().clear();
upperInfoArea.getChildren().add(content);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckEntry.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import net.demilich.metastone.ApplicationFacade;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.gui.IconFactory;
import net.demilich.metastone.gui.dialog.DialogNotification;
import net.demilich.metastone.gui.dialog.DialogResult;
import net.demilich.metastone.gui.dialog.DialogType;
public class DeckEntry extends HBox {
@FXML
private Label deckNameLabel;
@FXML
private ImageView classIcon;
@FXML
private Button deleteDeckButton;
private Deck deck;
public DeckEntry() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/DeckEntry.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
deleteDeckButton.setOnAction(this::handleDeleteDeck);
}
public Deck getDeck() {
return deck;
}
public void setDeck(Deck deck) {
this.deck = deck;
deckNameLabel.setText(deck.getName());
classIcon.setImage(IconFactory.getClassIcon(deck.getHeroClass()));
}
private void handleDeleteDeck(ActionEvent event) {
DialogNotification dialogNotification = new DialogNotification("Delete deck",
"Do you really want to delete the deck '" + deck.getName() + "'? This cannot be undone.", DialogType.WARNING);
dialogNotification.setHandler(this::onDeleteDeckDialog);
ApplicationFacade.getInstance().notifyObservers(dialogNotification);
}
private void onDeleteDeckDialog(DialogResult result) {
if (result == DialogResult.OK) {
NotificationProxy.sendNotification(GameNotification.DELETE_DECK, deck);
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckFormatProxy.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.demilich.metastone.utils.ResourceInputStream;
import net.demilich.metastone.utils.ResourceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.cards.CardSet;
import net.demilich.metastone.game.decks.DeckFormat;
import net.demilich.nittygrittymvc.Proxy;
public class DeckFormatProxy extends Proxy<GameNotification> {
private static Logger logger = LoggerFactory.getLogger(DeckFormatProxy.class);
public static final String NAME = "DeckFormatProxy";
private static final String DECK_FORMATS_FOLDER = "formats";
private final List<DeckFormat> deckFormats = new ArrayList<DeckFormat>();
public DeckFormatProxy() {
super(NAME);
}
public DeckFormat getDeckFormatByName(String deckName) {
for (DeckFormat deckFormat : deckFormats) {
if (deckFormat.getName().equals(deckName)) {
return deckFormat;
}
}
return null;
}
public List<DeckFormat> getDeckFormats() {
return deckFormats;
}
public void loadDeckFormats() throws IOException, URISyntaxException {
deckFormats.clear();
// load the deck formats from the resources in cards.jar file on the classpath
Collection<ResourceInputStream> inputStreams = ResourceLoader.loadJsonInputStreams(DECK_FORMATS_FOLDER, false);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
loadDeckFormats(inputStreams, gson);
}
private void loadDeckFormats(Collection<ResourceInputStream> inputStreams, Gson gson) throws FileNotFoundException {
for (ResourceInputStream resourceInputStream : inputStreams) {
Reader reader = new InputStreamReader(resourceInputStream.inputStream);
HashMap<String, Object> map = gson.fromJson(reader, new TypeToken<HashMap<String, Object>>() {}.getType());
if (!map.containsKey("sets")) {
logger.error("Deck {} does not specify a value for 'sets' and is therefore not valid", resourceInputStream.fileName);
continue;
}
String deckName = (String) map.get("name");
DeckFormat deckFormat = null;
// this one is a meta deck; we need to parse those after all other
// decks are done
deckFormat = parseStandardDeckFormat(map);
deckFormat.setName(deckName);
deckFormat.setFilename(resourceInputStream.fileName);
deckFormats.add(deckFormat);
}
}
private DeckFormat parseStandardDeckFormat(Map<String, Object> map) {
DeckFormat deckFormat = new DeckFormat();
@SuppressWarnings("unchecked")
List<String> setIds = (List<String>) map.get("sets");
for (String setId : setIds) {
for (CardSet set : CardSet.values()) {
if (set.toString().equalsIgnoreCase(setId)) {
deckFormat.addSet(set);
}
}
}
return deckFormat;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckInfoView.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import net.demilich.metastone.ApplicationFacade;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.MetaDeck;
import net.demilich.metastone.game.logic.GameLogic;
import net.demilich.metastone.gui.dialog.DialogNotification;
import net.demilich.metastone.gui.dialog.DialogResult;
import net.demilich.metastone.gui.dialog.DialogType;
import net.demilich.metastone.gui.dialog.IDialogListener;
public class DeckInfoView extends HBox implements EventHandler<ActionEvent>, IDialogListener {
@FXML
private Button doneButton;
@FXML
private Label typeLabel;
@FXML
private Label countLabel;
private Deck activeDeck;
public DeckInfoView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/DeckInfoView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
doneButton.setOnAction(this);
}
@Override
public void handle(ActionEvent event) {
if (activeDeck.isMetaDeck() && !activeDeck.isComplete()) {
DialogNotification dialogNotification = new DialogNotification("Warning",
"Your deck collection is not complete yet. Each deck collection has to contain at least 2 (or more) decks. ",
DialogType.WARNING);
ApplicationFacade.getInstance().notifyObservers(dialogNotification);
} else if (!activeDeck.isMetaDeck() && !activeDeck.isComplete() && !activeDeck.isTooBig() && !activeDeck.isArbitrary()) {
DialogNotification dialogNotification = new DialogNotification("Add random cards",
"Your deck is not complete yet. If you proceed, all open slots will be filled with random cards.", DialogType.CONFIRM);
dialogNotification.setHandler(this);
ApplicationFacade.getInstance().notifyObservers(dialogNotification);
} else if (!activeDeck.isMetaDeck() && !activeDeck.isComplete() && activeDeck.isTooBig() && !activeDeck.isArbitrary()) {
DialogNotification dialogNotification = new DialogNotification("Remove random cards",
"Your deck has too many cards. If you proceed, some cards will be removed at random.", DialogType.CONFIRM);
dialogNotification.setHandler(this);
ApplicationFacade.getInstance().notifyObservers(dialogNotification);
} else {
NotificationProxy.sendNotification(GameNotification.SAVE_ACTIVE_DECK);
}
}
@Override
public void onDialogClosed(DialogResult result) {
if (result == DialogResult.OK) {
NotificationProxy.sendNotification(GameNotification.FILL_DECK_WITH_RANDOM_CARDS);
NotificationProxy.sendNotification(GameNotification.SAVE_ACTIVE_DECK);
}
}
public void updateDeck(Deck deck) {
this.activeDeck = deck;
if (deck.isMetaDeck()) {
MetaDeck metaDeck = (MetaDeck) deck;
typeLabel.setText("Decks");
countLabel.setText(metaDeck.getDecks().size() + "");
} else {
typeLabel.setText("Cards");
if (deck.isTooBig()) {
countLabel.setText(deck.getCards().getCount() + "!/" + GameLogic.DECK_SIZE);
countLabel.setTextFill(Color.RED);
} else {
countLabel.setText(deck.getCards().getCount() + "/" + GameLogic.DECK_SIZE);
countLabel.setTextFill(Color.BLACK);
}
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckListView.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.IOException;
import java.util.List;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.decks.Deck;
public class DeckListView extends VBox implements EventHandler<MouseEvent> {
@FXML
private Button newDeckButton;
public DeckListView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/DeckListView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
newDeckButton.setOnAction(actionEvent -> NotificationProxy.sendNotification(GameNotification.CREATE_NEW_DECK));
setCache(true);
}
private void clearChildren() {
for (Node child : getChildren()) {
child.removeEventHandler(MouseEvent.MOUSE_CLICKED, this);
}
getChildren().clear();
}
public void displayDecks(List<Deck> decks) {
clearChildren();
getChildren().add(newDeckButton);
for (Deck deck : decks) {
DeckEntry deckEntry = new DeckEntry();
deckEntry.setDeck(deck);
deckEntry.addEventHandler(MouseEvent.MOUSE_CLICKED, this);
getChildren().add(deckEntry);
}
}
@Override
public void handle(MouseEvent event) {
DeckEntry deckEntry = (DeckEntry) event.getSource();
NotificationProxy.sendNotification(GameNotification.SET_ACTIVE_DECK, deckEntry.getDeck());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckNameView.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.IOException;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.gui.IconFactory;
public class DeckNameView extends HBox implements ChangeListener<String> {
@FXML
private ImageView classIcon;
@FXML
private TextField nameField;
public DeckNameView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/DeckNameView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
nameField.textProperty().addListener(this);
}
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
NotificationProxy.sendNotification(GameNotification.CHANGE_DECK_NAME, newValue);
}
public void updateDeck(Deck deck) {
classIcon.setImage(IconFactory.getClassIcon(deck.getHeroClass()));
nameField.setText(deck.getName());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckProxy.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.demilich.metastone.utils.MetastoneProperties;
import net.demilich.metastone.utils.ResourceInputStream;
import net.demilich.metastone.utils.ResourceLoader;
import net.demilich.metastone.utils.UserHomeMetastone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardCatalogue;
import net.demilich.metastone.game.cards.CardCollection;
import net.demilich.metastone.game.cards.CardSet;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.DeckFormat;
import net.demilich.metastone.game.decks.MetaDeck;
import net.demilich.metastone.game.entities.heroes.HeroClass;
import net.demilich.metastone.game.decks.validation.DefaultDeckValidator;
import net.demilich.metastone.game.decks.validation.IDeckValidator;
import net.demilich.nittygrittymvc.Proxy;
public class DeckProxy extends Proxy<GameNotification> {
private static Logger logger = LoggerFactory.getLogger(DeckProxy.class);
public static final String NAME = "DeckProxy";
private static final String DECKS_FOLDER = "decks";
private static final String DECKS_FOLDER_PATH = UserHomeMetastone.getPath() + File.separator + DECKS_FOLDER;
private static final String DECKS_COPIED_PROPERTY = "decks.copied";
private final List<Deck> decks = new ArrayList<Deck>();
private IDeckValidator activeDeckValidator = new DefaultDeckValidator();
private Deck activeDeck;
public DeckProxy() {
super(NAME);
try {
// ensure user's personal deck dir exists
Files.createDirectories(Paths.get(DECKS_FOLDER_PATH));
// ensure decks have been copied to ~/metastone/decks
copyDecksFromResources();
} catch (IOException e) {
logger.error("Trouble creating " + Paths.get(DECKS_FOLDER_PATH));
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
public boolean addCardToDeck(Card card) {
boolean result = activeDeckValidator.canAddCardToDeck(card, activeDeck);
if (result) {
activeDeck.getCards().add(card);
}
return result;
}
public Deck getActiveDeck() {
return activeDeck;
}
public List<Card> getCards(HeroClass heroClass) {
DeckFormat deckFormat = new DeckFormat();
for (CardSet cardSet : CardSet.values()) {
deckFormat.addSet(cardSet);
}
CardCollection cardCollection;
if (activeDeck.isArbitrary()) {
cardCollection = CardCatalogue.query(deckFormat);
} else {
cardCollection = CardCatalogue.query(deckFormat, heroClass);
// add neutral cards
cardCollection.addAll(CardCatalogue.query(deckFormat, HeroClass.ANY));
}
cardCollection.sortByName();
cardCollection.sortByManaCost();
return cardCollection.toList();
}
public Deck getDeckByName(String deckName) {
for (Deck deck : decks) {
if (deck.getName().equals(deckName)) {
return deck;
}
}
return null;
}
public List<Deck> getDecks() {
return decks;
}
public void deleteDeck(Deck deck) {
decks.remove(deck);
logger.debug("Trying to delete deck '{}' contained in file '{}'...", deck.getName(), deck.getFilename());
Path path = Paths.get(DECKS_FOLDER_PATH + File.separator + deck.getFilename());
try {
Files.delete(path);
} catch (NoSuchFileException x) {
logger.error("Could not delete deck '{}' as the filename '{}' does not exist", deck.getName(), path);
return;
} catch (IOException e) {
logger.error(e.getMessage());
logger.error("Could not delete file '{}'", path);
return;
}
logger.info("Deck '{}' contained in file '{}' has been successfully deleted", deck.getName(), path.getFileName().toString());
getFacade().sendNotification(GameNotification.DECKS_LOADED, decks);
}
public void loadDecks() throws IOException, URISyntaxException {
decks.clear();
// load decks from ~/metastone/decks on the filesystem
loadStandardDecks(ResourceLoader.loadJsonInputStreams(DECKS_FOLDER_PATH, true), new GsonBuilder().setPrettyPrinting().create());
loadMetaDecks(ResourceLoader.loadJsonInputStreams(DECKS_FOLDER_PATH, true), new GsonBuilder().setPrettyPrinting().create());
}
private void copyDecksFromResources() throws IOException, URISyntaxException {
// if we have not copied decks to the USER_HOME_METASTONE decks folder,
// then do so now
if (!MetastoneProperties.getBoolean(DECKS_COPIED_PROPERTY)) {
ResourceLoader.copyFromResources(DECKS_FOLDER, DECKS_FOLDER_PATH);
// set a property to indicate that we have copied decks
MetastoneProperties.setBoolean(DECKS_COPIED_PROPERTY, true);
}
}
private void loadMetaDecks(Collection<ResourceInputStream> inputStreams, Gson gson) throws IOException {
for (ResourceInputStream resourceInputStream : inputStreams) {
Reader reader = new InputStreamReader(resourceInputStream.inputStream);
HashMap<String, Object> map = gson.fromJson(reader, new TypeToken<HashMap<String, Object>>() {
}.getType());
if (!map.containsKey("heroClass")) {
logger.error("Deck {} does not specify a value for 'heroClass' and is therefor not valid", resourceInputStream.fileName);
continue;
}
String deckName = (String) map.get("name");
Deck deck = null;
if (!map.containsKey("decks")) {
continue;
} else {
deck = parseMetaDeck(map);
}
deck.setName(deckName);
deck.setFilename(resourceInputStream.fileName);
decks.add(deck);
}
}
private void loadStandardDecks(Collection<ResourceInputStream> inputStreams, Gson gson) throws FileNotFoundException {
for (ResourceInputStream resourceInputStream : inputStreams) {
Reader reader = new InputStreamReader(resourceInputStream.inputStream);
HashMap<String, Object> map = gson.fromJson(reader, new TypeToken<HashMap<String, Object>>() {
}.getType());
if (!map.containsKey("heroClass")) {
logger.error("Deck {} does not speficy a value for 'heroClass' and is therefor not valid", resourceInputStream.fileName);
continue;
}
HeroClass heroClass = HeroClass.valueOf((String) map.get("heroClass"));
String deckName = (String) map.get("name");
Deck deck = null;
// this one is a meta deck; we need to parse those after all other
// decks are done
if (map.containsKey("decks")) {
continue;
} else {
deck = parseStandardDeck(deckName, heroClass, map);
}
deck.setName(deckName);
deck.setFilename(resourceInputStream.fileName);
decks.add(deck);
}
}
public boolean nameAvailable(Deck deck) {
for (Deck existingDeck : decks) {
if (existingDeck != deck && existingDeck.getName().equals(deck.getName())) {
return false;
}
}
return true;
}
private Deck parseMetaDeck(Map<String, Object> map) {
@SuppressWarnings("unchecked")
List<String> referencedDecks = (List<String>) map.get("decks");
List<Deck> decksInMetaDeck = new ArrayList<>();
for (String deckName : referencedDecks) {
Deck deck = getDeckByName(deckName);
if (deck == null) {
logger.error("Metadeck {} contains invalid reference to deck {}", map.get("name"), deckName);
continue;
}
decksInMetaDeck.add(deck);
}
return new MetaDeck(decksInMetaDeck);
}
private Deck parseStandardDeck(String deckName, HeroClass heroClass, Map<String, Object> map) {
boolean arbitrary = false;
if (map.containsKey("arbitrary")) {
arbitrary = (boolean) map.get("arbitrary");
}
Deck deck = new Deck(heroClass, arbitrary);
@SuppressWarnings("unchecked")
List<String> cardIds = (List<String>) map.get("cards");
for (String cardId : cardIds) {
Card card = CardCatalogue.getCardById(cardId);
if (card == null) {
logger.error("Deck {} contains invalid cardId '{}'", deckName, cardId);
continue;
}
deck.getCards().add(card);
}
return deck;
}
public void removeCardFromDeck(Card card) {
activeDeck.getCards().remove(card);
}
public void saveActiveDeck() {
decks.add(activeDeck);
saveToJson(activeDeck);
activeDeck = null;
}
private void saveToJson(Deck deck) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
HashMap<String, Object> saveData = new HashMap<String, Object>();
saveData.put("name", deck.getName());
saveData.put("description", deck.getDescription());
saveData.put("arbitrary", deck.isArbitrary());
saveData.put("heroClass", deck.getHeroClass());
if (deck.isMetaDeck()) {
MetaDeck metaDeck = (MetaDeck) deck;
List<String> referencedDecks = new ArrayList<>();
for (Deck referencedDeck : metaDeck.getDecks()) {
referencedDecks.add(referencedDeck.getName());
}
saveData.put("decks", referencedDecks);
} else {
List<String> cardIds = new ArrayList<String>();
for (Card card : deck.getCards()) {
cardIds.add(card.getCardId());
}
saveData.put("cards", cardIds);
}
String jsonData = gson.toJson(saveData);
try {
String filename = deck.getName().toLowerCase();
filename = filename.replaceAll(" ", "_");
filename = filename.replaceAll("\\W+", "");
filename = DECKS_FOLDER_PATH + File.separator + filename + ".json";
Path path = Paths.get(filename);
Files.write(path, jsonData.getBytes());
deck.setFilename(path.getFileName().toString());
} catch (IOException e) {
e.printStackTrace();
}
}
public void setActiveDeck(Deck activeDeck) {
this.activeDeck = activeDeck;
}
public void setActiveDeckValidator(IDeckValidator deckValidator) {
this.activeDeckValidator = deckValidator;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeleteDeckCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
public class DeleteDeckCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
Deck deck = (Deck) notification.getBody();
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
deckProxy.deleteDeck(deck);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/FillDeckWithRandomCardsCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.decks.Deck;
public class FillDeckWithRandomCardsCommand extends SimpleCommand<GameNotification> {
private static Logger logger = LoggerFactory.getLogger(FillDeckWithRandomCardsCommand.class);
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
Deck activeDeck = deckProxy.getActiveDeck();
List<Card> cards = deckProxy.getCards(activeDeck.getHeroClass());
if (activeDeck.isTooBig()) {
while (!activeDeck.isComplete()) {
Card randomCard = activeDeck.getCards().getRandom();
deckProxy.removeCardFromDeck(randomCard);
logger.debug("Removing card {} to deck.", randomCard);
}
} else {
while (!activeDeck.isComplete()) {
Card randomCard = cards.get(ThreadLocalRandom.current().nextInt(cards.size()));
if (deckProxy.addCardToDeck(randomCard)) {
logger.debug("Adding card {} to deck.", randomCard);
}
}
}
getFacade().sendNotification(GameNotification.ACTIVE_DECK_CHANGED, activeDeck);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/FilterCardsCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardSet;
import net.demilich.metastone.game.decks.DeckFormat;
public class FilterCardsCommand extends SimpleCommand<GameNotification> {
private static List<Card> filterByFormat(List<Card> collection, DeckFormat format) {
if (format == null) {
return collection;
}
collection.removeIf(card -> !format.isInFormat(card));
return collection;
}
private static List<Card> filterBySet(List<Card> collection, CardSet set) {
if (set == CardSet.ANY) {
return collection;
}
collection.removeIf(card -> card.getCardSet() != set);
return collection;
}
private static List<Card> filterByText(List<Card> collection, String text) {
if (StringUtils.isBlank(text)) {
return collection;
}
String filterText = text.toLowerCase();
collection.removeIf(card -> !card.matchesFilter(filterText));
return collection;
}
@Override
public void execute(INotification<GameNotification> notification) {
CardFilter filter = (CardFilter) notification.getBody();
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
List<Card> cards = deckProxy.getCards(deckProxy.getActiveDeck().getHeroClass());
cards = filterByFormat(cards, filter.getFormat());
cards = filterBySet(cards, filter.getSet());
cards = filterByText(cards, filter.getText());
getFacade().sendNotification(GameNotification.FILTERED_CARDS, cards);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/ImportDeckCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import net.demilich.metastone.gui.deckbuilder.importer.ImporterFactory;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.gui.deckbuilder.importer.IDeckImporter;
import net.demilich.metastone.gui.dialog.DialogNotification;
import net.demilich.metastone.gui.dialog.DialogType;
public class ImportDeckCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
String url = (String) notification.getBody();
ImporterFactory factory = new ImporterFactory();
IDeckImporter importer = factory.createDeckImporter(url);
Deck importedDeck = null;
if(importer != null)
importedDeck = importer.importFrom(url);
if (importedDeck == null) {
DialogNotification dialogNotification = new DialogNotification("Error",
"Import of deck failed. Please make sure to provide a valid URL. At the moment, only hearthpwn.com, tempostorm.com, icy-veins.com, and heartheed.com are supported for deck import.",
DialogType.ERROR);
notifyObservers(dialogNotification);
return;
}
getFacade().sendNotification(GameNotification.SET_ACTIVE_DECK, importedDeck);
getFacade().sendNotification(GameNotification.SAVE_ACTIVE_DECK);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/LoadDeckFormatsCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
public class LoadDeckFormatsCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckFormatProxy deckFormatProxy = (DeckFormatProxy) getFacade().retrieveProxy(DeckFormatProxy.NAME);
try {
deckFormatProxy.loadDeckFormats();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
getFacade().sendNotification(GameNotification.DECK_FORMATS_LOADED, deckFormatProxy.getDeckFormats());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/LoadDecksCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
public class LoadDecksCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
try {
deckProxy.loadDecks();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
getFacade().sendNotification(GameNotification.DECKS_LOADED, deckProxy.getDecks());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/RemoveCardFromDeckCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.cards.Card;
public class RemoveCardFromDeckCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
Card card = (Card) notification.getBody();
deckProxy.getActiveDeck().getCards().remove(card);
getFacade().sendNotification(GameNotification.ACTIVE_DECK_CHANGED, deckProxy.getActiveDeck());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/SaveDeckCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
public class SaveDeckCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
String deckName = deckProxy.getActiveDeck().getName().trim();
if (deckName == null || deckName.equals("")) {
getFacade().sendNotification(GameNotification.INVALID_DECK_NAME);
return;
} else if (!deckProxy.nameAvailable(deckProxy.getActiveDeck())) {
getFacade().sendNotification(GameNotification.DUPLICATE_DECK_NAME);
return;
}
deckProxy.saveActiveDeck();
getFacade().removeMediator(DeckBuilderMediator.NAME);
getFacade().sendNotification(GameNotification.MAIN_MENU);
getFacade().sendNotification(GameNotification.DECK_BUILDER_SELECTED);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/SetActiveDeckCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.validation.ArbitraryDeckValidator;
import net.demilich.metastone.game.decks.validation.DefaultDeckValidator;
public class SetActiveDeckCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
Deck activeDeck = (Deck) notification.getBody();
if (activeDeck.isArbitrary()) {
deckProxy.setActiveDeckValidator(new ArbitraryDeckValidator());
} else {
deckProxy.setActiveDeckValidator(new DefaultDeckValidator());
}
deckProxy.setActiveDeck(activeDeck);
getFacade().sendNotification(GameNotification.EDIT_DECK, activeDeck);
getFacade().sendNotification(GameNotification.FILTERED_CARDS, deckProxy.getCards(activeDeck.getHeroClass()));
getFacade().sendNotification(GameNotification.ACTIVE_DECK_CHANGED, activeDeck);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/HearthHeadImporter.java
================================================
package net.demilich.metastone.gui.deckbuilder.importer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardCatalogue;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.entities.heroes.HeroClass;
public class HearthHeadImporter implements IDeckImporter {
private static Logger logger = LoggerFactory.getLogger(IcyVeinsImporter.class);
@Override
public Deck importFrom(String url) {
String exportUrl = url;
try {
return parse(exportUrl);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private List<String> getCardIds(Document doc){
Elements metas = doc.getElementsByTag("meta");
String title = "";
String cards = "";
for (int i = 0; i < metas.size(); i++) {
if (metas.get(i).attr("property").equals("x-hearthstone:deck:cards")) {
cards = metas.get(i).attr("content");
}
if (metas.get(i).attr("property").equals("x-hearthstone:deck")) {
title = metas.get(i).attr("content");
}
}
List<String> cs = new ArrayList<String>();
cs.add(0, title);
List<String> cids = Arrays.asList(cards.split(","));
for (String c: cids){
cs.add(c);
}
return cs;
}
private Deck parse(String url) throws IOException {
List<Card> cards = new ArrayList<Card>();
HeroClass heroClass = HeroClass.ANY;
Response response= Jsoup.connect(url)
.ignoreContentType(true)
.userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0")
.referrer("http://www.google.com")
.timeout(12000)
.followRedirects(true)
.execute();
Document doc = response.parse();
for (String cid: getCardIds(doc).subList(1, getCardIds(doc).size())) {
Card card = CardCatalogue.getCardByBlizzardId(cid);
if (card != null) {
cards.add(card);
if (card.getHeroClass() != HeroClass.ANY) {
heroClass = card.getHeroClass();
}
} else {
logger.error("Card with id {} could not be found", cid);
}
}
Deck deck = new Deck(heroClass);
deck.setName(getCardIds(doc).get(0));
for (Card card : cards) {
deck.getCards().add(card);
}
if (!deck.isComplete()) {
return null;
}
return deck;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/HearthPwnImporter.java
================================================
package net.demilich.metastone.gui.deckbuilder.importer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardCatalogue;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.entities.heroes.HeroClass;
public class HearthPwnImporter implements IDeckImporter {
private static Logger logger = LoggerFactory.getLogger(HearthPwnImporter.class);
private String extractId(String url) {
String result = "";
boolean digitEncountered = false;
for (int i = 0; i < url.length(); i++) {
char c = url.charAt(i);
if (Character.isDigit(c)) {
result += c;
digitEncountered = true;
} else if (digitEncountered) {
break;
}
}
return result;
}
private String getExportUrl(String url) {
String idString = extractId(url);
String result = "http://www.hearthpwn.com/decks/{}/export/2".replace("{}", idString);
return result;
}
@Override
public Deck importFrom(String url) {
try {
RequestConfig globalConfig = RequestConfig.custom().setCircularRedirectsAllowed(true).build();
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
String exportUrl = getExportUrl(url);
logger.debug("Requesting: " + exportUrl);
HttpGet httpGet = new HttpGet(exportUrl);
httpGet.setConfig(globalConfig);
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
HttpEntity entity = response.getEntity();
String htmlContent = EntityUtils.toString(entity);
EntityUtils.consume(entity);
return parse(htmlContent);
} finally {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private Deck parse(String htmlContent) {
List<Card> cards = new ArrayList<Card>();
HeroClass heroClass = HeroClass.ANY;
// remove html tags
htmlContent = htmlContent.replaceAll("\\<.+?\\>", "");
// remove BBCode tags
htmlContent = htmlContent.replaceAll("\\[.+?\\]", "");
// remove empty lines
htmlContent = htmlContent.replaceAll("(?m)^\\s+", "");
// unescape
htmlContent = StringEscapeUtils.unescapeHtml4(htmlContent);
String lines[] = htmlContent.split("\\r?\\n");
String deckName = lines[0];
for (String line : lines) {
if (!line.startsWith("1") && !line.startsWith("2")) {
continue;
}
int count = Integer.parseInt(String.valueOf(line.charAt(0)));
String cardName = line.substring(4);
for (int i = 0; i < count; i++) {
Card card = CardCatalogue.getCardByName(cardName);
if (card != null) {
cards.add(card);
if (card.getHeroClass() != HeroClass.ANY) {
heroClass = card.getHeroClass();
}
} else {
logger.error("Card with name {} could not be found", cardName);
}
}
}
Deck deck = new Deck(heroClass);
deck.setName(deckName);
for (Card card : cards) {
deck.getCards().add(card);
}
if (!deck.isComplete()) {
return null;
}
return deck;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/IDeckImporter.java
================================================
package net.demilich.metastone.gui.deckbuilder.importer;
import net.demilich.metastone.game.decks.Deck;
public interface IDeckImporter {
Deck importFrom(String uri);
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/IcyVeinsImporter.java
================================================
package net.demilich.metastone.gui.deckbuilder.importer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardCatalogue;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.entities.heroes.HeroClass;
public class IcyVeinsImporter implements IDeckImporter {
private static Logger logger = LoggerFactory.getLogger(IcyVeinsImporter.class);
@Override
public Deck importFrom(String url) {
try {
RequestConfig globalConfig = RequestConfig.custom().setCircularRedirectsAllowed(true).build();
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
String exportUrl = url;
logger.debug("Requesting: " + exportUrl);
HttpGet httpGet = new HttpGet(exportUrl);
httpGet.setConfig(globalConfig);
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
HttpEntity entity = response.getEntity();
String htmlContent = EntityUtils.toString(entity);
EntityUtils.consume(entity);
return parse(htmlContent);
} finally {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private Deck parse(String htmlContent) {
List<Card> cards = new ArrayList<Card>();
HeroClass heroClass = HeroClass.ANY;
Document doc = Jsoup.parse(htmlContent);
String deckName = doc.getElementsByClass("page_breadcrumbs_item").last().text();
Elements cardLines = doc.getElementsByClass("deck_card_list").get(0).getElementsByTag("li");
for (Element e: cardLines){
if (!e.text().startsWith("1") && !e.text().startsWith("2")) {
continue;
}
int count = Integer.parseInt(String.valueOf(e.text().charAt(0)));
String cardName = e.getElementsByTag("a").get(0).text();
for (int i = 0; i < count; i++){
Card card = CardCatalogue.getCardByName(cardName);
if (card != null) {
cards.add(card);
if (card.getHeroClass() != HeroClass.ANY) {
heroClass = card.getHeroClass();
}
} else {
logger.error("Card with name {} could not be found", cardName);
}
}
}
Deck deck = new Deck(heroClass);
deck.setName(deckName);
for (Card card : cards) {
deck.getCards().add(card);
logger.debug("Card added - {}", card.getName());
}
if (!deck.isComplete()) {
logger.error("Deck with name only has {}.", deck.getCards().toList().size());
return null;
}
return deck;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/ImporterFactory.java
================================================
package net.demilich.metastone.gui.deckbuilder.importer;
public class ImporterFactory {
public IDeckImporter createDeckImporter(String url)
{
if(url == null)
return null;
if(url.contains("hearthpwn.com"))
return new HearthPwnImporter();
if(url.contains("tempostorm.com"))
return new TempostormImporter();
if(url.contains("icy-veins.com"))
return new IcyVeinsImporter();
if(url.contains("hearthhead.com"))
return new HearthHeadImporter();
return null;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/TempostormImporter.java
================================================
package net.demilich.metastone.gui.deckbuilder.importer;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardCatalogue;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.entities.heroes.HeroClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TempostormImporter implements IDeckImporter{
private static Logger logger = LoggerFactory.getLogger(TempostormImporter.class);
Deck parse(JsonObject root)
{
try {
List<Card> cards = new ArrayList<Card>();
String deckName = root.get("name").getAsString();
String hero = root.get("playerClass").getAsString();
HeroClass heroClass = HeroClass.valueOf(hero.toUpperCase());
JsonElement cardsEl = root.get("cards");
JsonArray cardsArray = cardsEl.getAsJsonArray();
for (JsonElement cardTypeElem : cardsArray) {
JsonObject cardTypeObj = cardTypeElem.getAsJsonObject();
int cardCount = cardTypeObj.get("cardQuantity").getAsInt();
JsonObject cardObj = cardTypeObj.get("card").getAsJsonObject();
String cardName = cardObj.get("name").getAsString();
Card card = CardCatalogue.getCardByName(cardName);
if (card != null) {
if(cardCount > 0)
cards.add(card);
for (int i = 1; i < cardCount; i++)
cards.add(card.clone());
} else {
logger.error("Card with name {} could not be found", cardName);
return null;
}
}
Deck deck = new Deck(heroClass);
deck.setName(deckName);
for (Card card : cards)
deck.getCards().add(card);
if (!deck.isComplete())
return null;
return deck;
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
String convertUrl(String url)
{
Pattern pattern = Pattern.compile(".*/decks/([^/]+)$");
Matcher matcher = pattern.matcher(url);
if(!matcher.matches())
return null;
String identifier = matcher.group(1);
String filter = "{\"where\":{\"slug\":\"" + identifier
+ "\"},\"fields\":{},\"include\":[{\"relation\":\"cards\",\"scope\":{\"include\":[\"card\"]}}]}";
return "https://tempostorm.com/api/decks/findOne?filter=" + filter;
}
@Override
public Deck importFrom(String requestedUrl) {
String apiUrl = convertUrl(requestedUrl);
logger.debug("Requesting: " + apiUrl);
URL url;
try {
url = new URL(apiUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
HttpURLConnection request;
try {
request = (HttpURLConnection) url.openConnection();
request.connect();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject jobj = root.getAsJsonObject();
return parse(jobj);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/AddDeckToMetaDeckCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder.metadeck;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.MetaDeck;
import net.demilich.metastone.gui.deckbuilder.DeckProxy;
public class AddDeckToMetaDeckCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
MetaDeck metaDeck = (MetaDeck) deckProxy.getActiveDeck();
Deck deck = (Deck) notification.getBody();
if (metaDeck.getDecks().contains(deck)) {
return;
}
metaDeck.getDecks().add(deck);
getFacade().sendNotification(GameNotification.ACTIVE_DECK_CHANGED, deckProxy.getActiveDeck());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/MetaDeckListView.java
================================================
package net.demilich.metastone.gui.deckbuilder.metadeck;
import java.io.IOException;
import java.util.List;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.gui.deckbuilder.DeckEntry;
public class MetaDeckListView extends VBox implements EventHandler<MouseEvent> {
@FXML
private Button newDeckButton;
public MetaDeckListView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/MetaDeckListView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
setCache(true);
}
public void displayDecks(List<Deck> decks) {
getChildren().clear();
for (Deck deck : decks) {
DeckEntry deckEntry = new DeckEntry();
deckEntry.setDeck(deck);
deckEntry.addEventHandler(MouseEvent.MOUSE_CLICKED, this);
getChildren().add(deckEntry);
}
}
@Override
public void handle(MouseEvent event) {
DeckEntry deckEntry = (DeckEntry) event.getSource();
NotificationProxy.sendNotification(GameNotification.REMOVE_DECK_FROM_META_DECK, deckEntry.getDeck());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/MetaDeckView.java
================================================
package net.demilich.metastone.gui.deckbuilder.metadeck;
import java.io.IOException;
import java.util.List;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.MetaDeck;
import net.demilich.metastone.gui.IconFactory;
public class MetaDeckView extends BorderPane {
@FXML
private Pane contentPane;
public MetaDeckView() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/MetaDeckView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
setCache(true);
}
public void deckChanged(MetaDeck metaDeck) {
for (Node node : contentPane.getChildren()) {
Deck deck = (Deck) node.getUserData();
node.setDisable(metaDeck.getDecks().contains(deck));
}
}
public void displayDecks(List<Deck> decks) {
contentPane.getChildren().clear();
for (Deck deck : decks) {
if (deck.isMetaDeck()) {
continue;
}
ImageView graphic = new ImageView(IconFactory.getClassIcon(deck.getHeroClass()));
graphic.setFitWidth(48);
graphic.setFitHeight(48);
Button deckButton = new Button(deck.getName(), graphic);
deckButton.setMaxWidth(160);
deckButton.setMinWidth(160);
deckButton.setMaxHeight(120);
deckButton.setMinHeight(120);
deckButton.setWrapText(true);
deckButton.setContentDisplay(ContentDisplay.LEFT);
deckButton.setOnAction(event -> NotificationProxy.sendNotification(GameNotification.ADD_DECK_TO_META_DECK, deck));
deckButton.setUserData(deck);
contentPane.getChildren().add(deckButton);
}
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/RemoveDeckFromMetaDeckCommand.java
================================================
package net.demilich.metastone.gui.deckbuilder.metadeck;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.decks.Deck;
import net.demilich.metastone.game.decks.MetaDeck;
import net.demilich.metastone.gui.deckbuilder.DeckProxy;
public class RemoveDeckFromMetaDeckCommand extends SimpleCommand<GameNotification> {
@Override
public void execute(INotification<GameNotification> notification) {
DeckProxy deckProxy = (DeckProxy) getFacade().retrieveProxy(DeckProxy.NAME);
MetaDeck metaDeck = (MetaDeck) deckProxy.getActiveDeck();
Deck deck = (Deck) notification.getBody();
if (!metaDeck.getDecks().contains(deck)) {
return;
}
metaDeck.getDecks().remove(deck);
getFacade().sendNotification(GameNotification.ACTIVE_DECK_CHANGED, deckProxy.getActiveDeck());
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/DialogMediator.java
================================================
package net.demilich.metastone.gui.dialog;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.nittygrittymvc.Mediator;
import net.demilich.nittygrittymvc.interfaces.INotification;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.Pane;
import javafx.stage.Window;
import net.demilich.metastone.GameNotification;
public class DialogMediator extends Mediator<GameNotification> {
public static final String NAME = "DialogMediator";
private static Logger logger = LoggerFactory.getLogger(DialogMediator.class);
private Window root;
public DialogMediator() {
super(NAME);
}
@Override
public void handleNotification(final INotification<GameNotification> notification) {
switch (notification.getId()) {
case CANVAS_CREATED:
Pane canvas = (Pane) notification.getBody();
root = canvas.getScene().getWindow();
break;
case SHOW_USER_DIALOG:
showUserDialog((DialogNotification) notification);
break;
case SHOW_MODAL_DIALOG:
showModalDialog((Node) notification.getBody());
break;
case CARD_PARSE_ERROR:
displayErrorMessage("Something is wrong with your card files", (String) notification.getBody());
break;
default:
logger.warn("Unhandled notification {} in {}", notification, getClass().getSimpleName());
break;
}
}
@Override
public List<GameNotification> listNotificationInterests() {
List<GameNotification> notificationInterests = new ArrayList<GameNotification>();
notificationInterests.add(GameNotification.CANVAS_CREATED);
notificationInterests.add(GameNotification.SHOW_MODAL_DIALOG);
notificationInterests.add(GameNotification.SHOW_USER_DIALOG);
notificationInterests.add(GameNotification.CARD_PARSE_ERROR);
return notificationInterests;
}
private void displayErrorMessage(String header, String message) {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText(header);
alert.setContentText(message);
alert.showAndWait();
}
private void showModalDialog(Node content) {
new ModalDialog(root, content);
}
private void showUserDialog(DialogNotification notification) {
UserDialog userDialog = new UserDialog(notification.getTitle(), notification.getMessage(), notification.getDialogType());
userDialog.setDialogHandler(notification.getHandler());
showModalDialog(userDialog);
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/DialogNotification.java
================================================
package net.demilich.metastone.gui.dialog;
import net.demilich.nittygrittymvc.Notification;
import net.demilich.metastone.GameNotification;
public class DialogNotification extends Notification<GameNotification> {
private final String title;
private final String message;
private final DialogType dialogType;
private IDialogListener handler;
public DialogNotification(String title, String message, DialogType dialogType) {
super(GameNotification.SHOW_USER_DIALOG);
this.title = title;
this.message = message;
this.dialogType = dialogType;
}
public DialogType getDialogType() {
return dialogType;
}
public IDialogListener getHandler() {
return handler;
}
public String getMessage() {
return message;
}
public String getTitle() {
return title;
}
public void setHandler(IDialogListener handler) {
this.handler = handler;
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/DialogResult.java
================================================
package net.demilich.metastone.gui.dialog;
public enum DialogResult {
OK, CANCEL
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/DialogType.java
================================================
package net.demilich.metastone.gui.dialog;
public enum DialogType {
CONFIRM, INFO, WARNING, ERROR,
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/IDialogListener.java
================================================
package net.demilich.metastone.gui.dialog;
public interface IDialogListener {
void onDialogClosed(DialogResult result);
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/ModalDialog.java
================================================
package net.demilich.metastone.gui.dialog;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
public class ModalDialog extends StackPane {
public ModalDialog(Window parent, Node content) {
Stage stage = new Stage();
Scene scene = new Scene(this);
scene.setFill(null);
stage.setScene(scene);
stage.initModality(Modality.WINDOW_MODAL);
stage.initStyle(StageStyle.TRANSPARENT);
stage.initOwner(parent);
stage.setX(parent.getX());
stage.setY(parent.getY());
setPrefSize(parent.getWidth(), parent.getHeight());
setStyle("-fx-background-color: rgba(0, 0, 0, 0.5);");
getChildren().add(content);
stage.show();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/UserDialog.java
================================================
package net.demilich.metastone.gui.dialog;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import net.demilich.metastone.gui.IconFactory;
public class UserDialog extends BorderPane implements EventHandler<ActionEvent> {
@FXML
private Label headerLabel;
@FXML
private Label textLabel;
@FXML
private ImageView icon;
@FXML
private Button positiveButton;
@FXML
private Button negativeButton;
private IDialogListener dialogHandler;
public UserDialog(String title, String message, DialogType dialogType) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/UserDialog.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
icon.setImage(IconFactory.getDialogIcon(dialogType));
headerLabel.setText(title);
textLabel.setText(message);
positiveButton.setOnAction(this);
negativeButton.setOnAction(this);
}
@Override
public void handle(ActionEvent event) {
if (event.getSource() == positiveButton) {
setDialogResult(DialogResult.OK);
} else if (event.getSource() == negativeButton) {
setDialogResult(DialogResult.CANCEL);
}
}
public void setDialogHandler(IDialogListener dialogHandler) {
this.dialogHandler = dialogHandler;
}
private void setDialogResult(DialogResult result) {
if (dialogHandler != null) {
dialogHandler.onDialogClosed(result);
}
this.getScene().getWindow().hide();
}
}
================================================
FILE: app/src/main/java/net/demilich/metastone/gui/gameconfig/PlayerConfigView.java
================================================
package net.demilich.metastone.gui.gameconfig;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
gitextract_a_mhvwr6/
├── .gitignore
├── LICENSE
├── README.md
├── app/
│ ├── build.fxbuild
│ ├── build.gradle
│ ├── javafx.plugin
│ ├── lib/
│ │ ├── controlsfx-8.40.10-20151003.010657-492.jar
│ │ └── nitty-gritty-mvc.jar
│ ├── manifest.json
│ └── src/
│ ├── deploy/
│ │ └── package/
│ │ └── windows/
│ │ └── Metastone.iss
│ └── main/
│ ├── java/
│ │ └── net/
│ │ └── demilich/
│ │ └── metastone/
│ │ ├── ApplicationFacade.java
│ │ ├── ApplicationStartupCommand.java
│ │ ├── DevCardTools.java
│ │ ├── MetaStone.java
│ │ ├── PlayGameCommand.java
│ │ ├── gui/
│ │ │ ├── DigitFactory.java
│ │ │ ├── DigitTemplate.java
│ │ │ ├── IconFactory.java
│ │ │ ├── autoupdate/
│ │ │ │ ├── AutoUpdateMediator.java
│ │ │ │ └── CheckForUpdateCommand.java
│ │ │ ├── battleofdecks/
│ │ │ │ ├── BattleBatchResult.java
│ │ │ │ ├── BattleBatchResultToken.java
│ │ │ │ ├── BattleConfig.java
│ │ │ │ ├── BattleDeckResult.java
│ │ │ │ ├── BattleOfDecksConfigView.java
│ │ │ │ ├── BattleOfDecksMediator.java
│ │ │ │ ├── BattleOfDecksResultView.java
│ │ │ │ ├── BattleResult.java
│ │ │ │ └── StartBattleOfDecksCommand.java
│ │ │ ├── cards/
│ │ │ │ ├── CardProxy.java
│ │ │ │ ├── CardToken.java
│ │ │ │ ├── CardTokenFactory.java
│ │ │ │ ├── CardTooltip.java
│ │ │ │ └── HandCard.java
│ │ │ ├── common/
│ │ │ │ ├── BehaviourStringConverter.java
│ │ │ │ ├── CardSetStringConverter.java
│ │ │ │ ├── ComboBoxKeyHandler.java
│ │ │ │ ├── DeckFormatStringConverter.java
│ │ │ │ ├── DeckStringConverter.java
│ │ │ │ ├── HeroStringConverter.java
│ │ │ │ ├── IntegerTextField.java
│ │ │ │ └── RestrictedTextField.java
│ │ │ ├── deckbuilder/
│ │ │ │ ├── AddCardToDeckCommand.java
│ │ │ │ ├── CardEntry.java
│ │ │ │ ├── CardEntryFactory.java
│ │ │ │ ├── CardFilter.java
│ │ │ │ ├── CardFilterView.java
│ │ │ │ ├── CardListView.java
│ │ │ │ ├── CardView.java
│ │ │ │ ├── ChangeDeckNameCommand.java
│ │ │ │ ├── ChooseClassView.java
│ │ │ │ ├── DeckBuilderMediator.java
│ │ │ │ ├── DeckBuilderView.java
│ │ │ │ ├── DeckEntry.java
│ │ │ │ ├── DeckFormatProxy.java
│ │ │ │ ├── DeckInfoView.java
│ │ │ │ ├── DeckListView.java
│ │ │ │ ├── DeckNameView.java
│ │ │ │ ├── DeckProxy.java
│ │ │ │ ├── DeleteDeckCommand.java
│ │ │ │ ├── FillDeckWithRandomCardsCommand.java
│ │ │ │ ├── FilterCardsCommand.java
│ │ │ │ ├── ImportDeckCommand.java
│ │ │ │ ├── LoadDeckFormatsCommand.java
│ │ │ │ ├── LoadDecksCommand.java
│ │ │ │ ├── RemoveCardFromDeckCommand.java
│ │ │ │ ├── SaveDeckCommand.java
│ │ │ │ ├── SetActiveDeckCommand.java
│ │ │ │ ├── importer/
│ │ │ │ │ ├── HearthHeadImporter.java
│ │ │ │ │ ├── HearthPwnImporter.java
│ │ │ │ │ ├── IDeckImporter.java
│ │ │ │ │ ├── IcyVeinsImporter.java
│ │ │ │ │ ├── ImporterFactory.java
│ │ │ │ │ └── TempostormImporter.java
│ │ │ │ └── metadeck/
│ │ │ │ ├── AddDeckToMetaDeckCommand.java
│ │ │ │ ├── MetaDeckListView.java
│ │ │ │ ├── MetaDeckView.java
│ │ │ │ └── RemoveDeckFromMetaDeckCommand.java
│ │ │ ├── dialog/
│ │ │ │ ├── DialogMediator.java
│ │ │ │ ├── DialogNotification.java
│ │ │ │ ├── DialogResult.java
│ │ │ │ ├── DialogType.java
│ │ │ │ ├── IDialogListener.java
│ │ │ │ ├── ModalDialog.java
│ │ │ │ └── UserDialog.java
│ │ │ ├── gameconfig/
│ │ │ │ └── PlayerConfigView.java
│ │ │ ├── main/
│ │ │ │ └── ApplicationMediator.java
│ │ │ ├── mainmenu/
│ │ │ │ ├── MainMenuMediator.java
│ │ │ │ └── MainMenuView.java
│ │ │ ├── playmode/
│ │ │ │ ├── GameBoardView.java
│ │ │ │ ├── GameContextVisualizable.java
│ │ │ │ ├── GameToken.java
│ │ │ │ ├── HeroToken.java
│ │ │ │ ├── HumanActionPromptView.java
│ │ │ │ ├── HumanMulliganView.java
│ │ │ │ ├── LoadingBoardView.java
│ │ │ │ ├── PlayModeMediator.java
│ │ │ │ ├── PlayModeView.java
│ │ │ │ ├── StartGameCommand.java
│ │ │ │ ├── SummonToken.java
│ │ │ │ ├── animation/
│ │ │ │ │ ├── AnimationCompletedCommand.java
│ │ │ │ │ ├── AnimationLockCommand.java
│ │ │ │ │ ├── AnimationProxy.java
│ │ │ │ │ ├── AnimationStartedCommand.java
│ │ │ │ │ ├── CardPlayedToken.java
│ │ │ │ │ ├── CardRevealedToken.java
│ │ │ │ │ ├── DamageEventVisualizer.java
│ │ │ │ │ ├── DamageNumber.java
│ │ │ │ │ ├── EventVisualizerDispatcher.java
│ │ │ │ │ ├── HealEventVisualizer.java
│ │ │ │ │ ├── HealingNumber.java
│ │ │ │ │ ├── IAnimationListener.java
│ │ │ │ │ ├── IGameEventVisualizer.java
│ │ │ │ │ ├── JoustToken.java
│ │ │ │ │ ├── JoustVisualizer.java
│ │ │ │ │ ├── PlayCardVisualizer.java
│ │ │ │ │ └── RevealCardVisualizer.java
│ │ │ │ └── config/
│ │ │ │ ├── PlayModeConfigMediator.java
│ │ │ │ ├── PlayModeConfigView.java
│ │ │ │ ├── PlayerConfigType.java
│ │ │ │ ├── RequestDeckFormatsCommand.java
│ │ │ │ └── RequestDecksCommand.java
│ │ │ ├── sandboxmode/
│ │ │ │ ├── CardCollectionEditor.java
│ │ │ │ ├── CardPanel.java
│ │ │ │ ├── EntityEditor.java
│ │ │ │ ├── GameTagEntry.java
│ │ │ │ ├── ICardCollectionEditingListener.java
│ │ │ │ ├── MinionPanel.java
│ │ │ │ ├── PlayerPanel.java
│ │ │ │ ├── SandboxEditor.java
│ │ │ │ ├── SandboxModeConfigView.java
│ │ │ │ ├── SandboxModeMediator.java
│ │ │ │ ├── SandboxModeView.java
│ │ │ │ ├── SandboxProxy.java
│ │ │ │ ├── ToolboxView.java
│ │ │ │ ├── actions/
│ │ │ │ │ ├── EditEntityAction.java
│ │ │ │ │ ├── KillAction.java
│ │ │ │ │ ├── SetManaAction.java
│ │ │ │ │ ├── SetMaxManaAction.java
│ │ │ │ │ └── SilenceAction.java
│ │ │ │ └── commands/
│ │ │ │ ├── CreateNewSandboxCommand.java
│ │ │ │ ├── ModifyPlayerDeckCommand.java
│ │ │ │ ├── ModifyPlayerHandCommand.java
│ │ │ │ ├── PerformActionCommand.java
│ │ │ │ ├── SelectPlayerCommand.java
│ │ │ │ ├── SpawnMinionCommand.java
│ │ │ │ ├── StartPlaySandboxCommand.java
│ │ │ │ └── StopPlaySandboxCommand.java
│ │ │ ├── simulationmode/
│ │ │ │ ├── PlayerConfigView.java
│ │ │ │ ├── PlayerInfoView.java
│ │ │ │ ├── SimulateGamesCommand.java
│ │ │ │ ├── SimulationMediator.java
│ │ │ │ ├── SimulationModeConfigView.java
│ │ │ │ ├── SimulationResult.java
│ │ │ │ ├── SimulationResultView.java
│ │ │ │ ├── StatEntry.java
│ │ │ │ └── WaitForSimulationView.java
│ │ │ └── trainingmode/
│ │ │ ├── PerformTrainingCommand.java
│ │ │ ├── RequestTrainingDataCommand.java
│ │ │ ├── SaveTrainingDataCommand.java
│ │ │ ├── TrainingConfig.java
│ │ │ ├── TrainingConfigView.java
│ │ │ ├── TrainingModeMediator.java
│ │ │ ├── TrainingModeView.java
│ │ │ ├── TrainingProgressReport.java
│ │ │ └── TrainingProxy.java
│ │ └── tools/
│ │ ├── CardCreator.java
│ │ ├── CardEditor.java
│ │ ├── EditorMainWindow.java
│ │ ├── ICardEditor.java
│ │ ├── ITextFieldAction.java
│ │ ├── IntegerListener.java
│ │ ├── MinionCardPanel.java
│ │ ├── SpellCardPanel.java
│ │ ├── SpellDescSerializer.java
│ │ ├── SpellStringConverter.java
│ │ └── WeaponClassPanel.java
│ └── resources/
│ ├── css/
│ │ ├── deckbuilder.css
│ │ ├── gameboard.css
│ │ ├── main.css
│ │ └── mainmenu.css
│ ├── fxml/
│ │ ├── BattleBatchResultToken.fxml
│ │ ├── BattleOfDecksConfigView.fxml
│ │ ├── BattleOfDecksResultView.fxml
│ │ ├── CardCollectionEditor.fxml
│ │ ├── CardEntry.fxml
│ │ ├── CardFilterView.fxml
│ │ ├── CardPanel.fxml
│ │ ├── CardTooltip.fxml
│ │ ├── CardView.fxml
│ │ ├── ChooseClassView.fxml
│ │ ├── DeckBuilderView.fxml
│ │ ├── DeckEntry.fxml
│ │ ├── DeckInfoView.fxml
│ │ ├── DeckListView.fxml
│ │ ├── DeckNameView.fxml
│ │ ├── DigitTemplate.fxml
│ │ ├── EditorMainWindow.fxml
│ │ ├── EntityEditor.fxml
│ │ ├── GameBoardView.fxml
│ │ ├── HandCard.fxml
│ │ ├── HeroToken.fxml
│ │ ├── HumanMulliganView.fxml
│ │ ├── LoadingBoardView.fxml
│ │ ├── MainMenuView.fxml
│ │ ├── MetaDeckListView.fxml
│ │ ├── MetaDeckView (2).fxml
│ │ ├── MetaDeckView.fxml
│ │ ├── MinionCardPanel.fxml
│ │ ├── MinionPanel.fxml
│ │ ├── PlayModeConfigView.fxml
│ │ ├── PlayModeView.fxml
│ │ ├── PlayerConfigView.fxml
│ │ ├── PlayerInfoView.fxml
│ │ ├── PlayerPanel.fxml
│ │ ├── SandboxModeConfigView.fxml
│ │ ├── SandboxModeView.fxml
│ │ ├── SimulationModeConfigView.fxml
│ │ ├── SimulationResultView.fxml
│ │ ├── SpellCardPanel.fxml
│ │ ├── SummonToken.fxml
│ │ ├── ToolboxView.fxml
│ │ ├── TrainingConfigView.fxml
│ │ ├── TrainingModeView.fxml
│ │ ├── UserDialog.fxml
│ │ └── WaitForSimulationView.fxml
│ └── logback.xml
├── build.gradle
├── cards/
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ └── resources/
│ │ ├── cards/
│ │ │ ├── basic/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── hero_malfurion.json
│ │ │ │ │ ├── hero_power_shapeshift.json
│ │ │ │ │ ├── minion_ironbark_protector.json
│ │ │ │ │ ├── spell_claw.json
│ │ │ │ │ ├── spell_excess_mana.json
│ │ │ │ │ ├── spell_healing_touch.json
│ │ │ │ │ ├── spell_innervate.json
│ │ │ │ │ ├── spell_mark_of_the_wild.json
│ │ │ │ │ ├── spell_moonfire.json
│ │ │ │ │ ├── spell_savage_roar.json
│ │ │ │ │ ├── spell_starfire.json
│ │ │ │ │ ├── spell_swipe.json
│ │ │ │ │ └── spell_wild_growth.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── hero_power_steady_shot.json
│ │ │ │ │ ├── hero_rexxar.json
│ │ │ │ │ ├── minion_houndmaster.json
│ │ │ │ │ ├── minion_starving_buzzard.json
│ │ │ │ │ ├── minion_timber_wolf.json
│ │ │ │ │ ├── minion_tundra_rhino.json
│ │ │ │ │ ├── spell_animal_companion.json
│ │ │ │ │ ├── spell_arcane_shot.json
│ │ │ │ │ ├── spell_hunters_mark.json
│ │ │ │ │ ├── spell_kill_command.json
│ │ │ │ │ ├── spell_multi-shot.json
│ │ │ │ │ ├── spell_tracking.json
│ │ │ │ │ ├── token_huffer.json
│ │ │ │ │ ├── token_leokk.json
│ │ │ │ │ └── token_misha.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── hero_jaina.json
│ │ │ │ │ ├── hero_power_fireblast.json
│ │ │ │ │ ├── minion_water_elemental.json
│ │ │ │ │ ├── spell_arcane_explosion.json
│ │ │ │ │ ├── spell_arcane_intellect.json
│ │ │ │ │ ├── spell_arcane_missiles.json
│ │ │ │ │ ├── spell_fireball.json
│ │ │ │ │ ├── spell_flamestrike.json
│ │ │ │ │ ├── spell_frost_nova.json
│ │ │ │ │ ├── spell_frostbolt.json
│ │ │ │ │ ├── spell_mirror_image.json
│ │ │ │ │ ├── spell_polymorph.json
│ │ │ │ │ ├── token_mirror_image.json
│ │ │ │ │ └── token_sheep.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_acidic_swamp_ooze.json
│ │ │ │ │ ├── minion_archmage.json
│ │ │ │ │ ├── minion_bloodfen_raptor.json
│ │ │ │ │ ├── minion_bluegill_warrior.json
│ │ │ │ │ ├── minion_booty_bay_bodyguard.json
│ │ │ │ │ ├── minion_boulderfist_ogre.json
│ │ │ │ │ ├── minion_chillwind_yeti.json
│ │ │ │ │ ├── minion_core_hound.json
│ │ │ │ │ ├── minion_dalaran_mage.json
│ │ │ │ │ ├── minion_darkscale_healer.json
│ │ │ │ │ ├── minion_dragonling_mechanic.json
│ │ │ │ │ ├── minion_elven_archer.json
│ │ │ │ │ ├── minion_frostwolf_grunt.json
│ │ │ │ │ ├── minion_frostwolf_warlord.json
│ │ │ │ │ ├── minion_gnomish_inventor.json
│ │ │ │ │ ├── minion_goldshire_footman.json
│ │ │ │ │ ├── minion_grimscale_oracle.json
│ │ │ │ │ ├── minion_gurubashi_berserker.json
│ │ │ │ │ ├── minion_ironforge_rifleman.json
│ │ │ │ │ ├── minion_ironfur_grizzly.json
│ │ │ │ │ ├── minion_kobold_geomancer.json
│ │ │ │ │ ├── minion_lord_of_the_arena.json
│ │ │ │ │ ├── minion_magma_rager.json
│ │ │ │ │ ├── minion_murloc_raider.json
│ │ │ │ │ ├── minion_murloc_tidehunter.json
│ │ │ │ │ ├── minion_nightblade.json
│ │ │ │ │ ├── minion_novice_engineer.json
│ │ │ │ │ ├── minion_oasis_snapjaw.json
│ │ │ │ │ ├── minion_ogre_magi.json
│ │ │ │ │ ├── minion_raid_leader.json
│ │ │ │ │ ├── minion_razorfen_hunter.json
│ │ │ │ │ ├── minion_reckless_rocketeer.json
│ │ │ │ │ ├── minion_river_crocolisk.json
│ │ │ │ │ ├── minion_senjin_shieldmasta.json
│ │ │ │ │ ├── minion_shattered_sun_cleric.json
│ │ │ │ │ ├── minion_silverback_patriarch.json
│ │ │ │ │ ├── minion_stonetusk_boar.json
│ │ │ │ │ ├── minion_stormpike_commando.json
│ │ │ │ │ ├── minion_stormwind_champion.json
│ │ │ │ │ ├── minion_stormwind_knight.json
│ │ │ │ │ ├── minion_voodoo_doctor.json
│ │ │ │ │ ├── minion_war_golem.json
│ │ │ │ │ ├── minion_wolfrider.json
│ │ │ │ │ ├── spell_the_coin.json
│ │ │ │ │ ├── token_boar.json
│ │ │ │ │ ├── token_mechanical_dragonling.json
│ │ │ │ │ └── token_murloc_scout.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── hero_power_reinforce.json
│ │ │ │ │ ├── hero_uther.json
│ │ │ │ │ ├── minion_guardian_of_kings.json
│ │ │ │ │ ├── spell_blessing_of_kings.json
│ │ │ │ │ ├── spell_blessing_of_might.json
│ │ │ │ │ ├── spell_consecration.json
│ │ │ │ │ ├── spell_hammer_of_wrath.json
│ │ │ │ │ ├── spell_hand_of_protection.json
│ │ │ │ │ ├── spell_holy_light.json
│ │ │ │ │ ├── spell_humility.json
│ │ │ │ │ ├── token_silver_hand_recruit.json
│ │ │ │ │ ├── weapon_lights_justice.json
│ │ │ │ │ └── weapon_truesilver_champion.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── hero_anduin.json
│ │ │ │ │ ├── hero_power_lesser_heal.json
│ │ │ │ │ ├── minion_northshire_cleric.json
│ │ │ │ │ ├── spell_divine_spirit.json
│ │ │ │ │ ├── spell_holy_nova.json
│ │ │ │ │ ├── spell_holy_smite.json
│ │ │ │ │ ├── spell_mind_blast.json
│ │ │ │ │ ├── spell_mind_control.json
│ │ │ │ │ ├── spell_mind_vision.json
│ │ │ │ │ ├── spell_power_word_shield.json
│ │ │ │ │ ├── spell_shadow_word_death.json
│ │ │ │ │ └── spell_shadow_word_pain.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── hero_power_dagger_mastery.json
│ │ │ │ │ ├── hero_valeera.json
│ │ │ │ │ ├── spell_assassinate.json
│ │ │ │ │ ├── spell_backstab.json
│ │ │ │ │ ├── spell_deadly_poison.json
│ │ │ │ │ ├── spell_fan_of_knives.json
│ │ │ │ │ ├── spell_sap.json
│ │ │ │ │ ├── spell_shiv.json
│ │ │ │ │ ├── spell_sinister_strike.json
│ │ │ │ │ ├── spell_sprint.json
│ │ │ │ │ ├── spell_vanish.json
│ │ │ │ │ ├── weapon_assassins_blade.json
│ │ │ │ │ └── weapon_wicked_knife.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── hero_power_totemic_call.json
│ │ │ │ │ ├── hero_thrall.json
│ │ │ │ │ ├── minion_fire_elemental.json
│ │ │ │ │ ├── minion_flametongue_totem.json
│ │ │ │ │ ├── minion_windspeaker.json
│ │ │ │ │ ├── spell_ancestral_healing.json
│ │ │ │ │ ├── spell_bloodlust.json
│ │ │ │ │ ├── spell_frost_shock.json
│ │ │ │ │ ├── spell_hex.json
│ │ │ │ │ ├── spell_rockbiter_weapon.json
│ │ │ │ │ ├── spell_totemic_might.json
│ │ │ │ │ ├── spell_windfury.json
│ │ │ │ │ ├── token_frog.json
│ │ │ │ │ ├── token_healing_totem.json
│ │ │ │ │ ├── token_searing_totem.json
│ │ │ │ │ ├── token_stoneclaw_totem.json
│ │ │ │ │ └── token_wrath_of_air_totem.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── hero_guldan.json
│ │ │ │ │ ├── hero_power_life_tap.json
│ │ │ │ │ ├── minion_dread_infernal.json
│ │ │ │ │ ├── minion_succubus.json
│ │ │ │ │ ├── minion_voidwalker.json
│ │ │ │ │ ├── spell_corruption.json
│ │ │ │ │ ├── spell_drain_life.json
│ │ │ │ │ ├── spell_hellfire.json
│ │ │ │ │ ├── spell_mortal_coil.json
│ │ │ │ │ ├── spell_sacrificial_pact.json
│ │ │ │ │ ├── spell_shadow_bolt.json
│ │ │ │ │ └── spell_soulfire.json
│ │ │ │ └── warrior/
│ │ │ │ ├── hero_garrosh.json
│ │ │ │ ├── hero_power_armor_up.json
│ │ │ │ ├── minion_korkron_elite.json
│ │ │ │ ├── minion_warsong_commander.json
│ │ │ │ ├── spell_charge.json
│ │ │ │ ├── spell_cleave.json
│ │ │ │ ├── spell_execute.json
│ │ │ │ ├── spell_heroic_strike.json
│ │ │ │ ├── spell_shield_block.json
│ │ │ │ ├── spell_whirlwind.json
│ │ │ │ ├── weapon_arcanite_reaper.json
│ │ │ │ └── weapon_fiery_war_axe.json
│ │ │ ├── blackrock_mountain/
│ │ │ │ ├── hero_power_die_insect.json
│ │ │ │ ├── hero_ragnaros.json
│ │ │ │ ├── minion_axe_flinger.json
│ │ │ │ ├── minion_blackwing_corruptor.json
│ │ │ │ ├── minion_blackwing_technician.json
│ │ │ │ ├── minion_chromaggus.json
│ │ │ │ ├── minion_core_rager.json
│ │ │ │ ├── minion_dark_iron_skulker.json
│ │ │ │ ├── minion_dragon_consort.json
│ │ │ │ ├── minion_dragon_egg.json
│ │ │ │ ├── minion_dragonkin_sorcerer.json
│ │ │ │ ├── minion_drakonid_crusher.json
│ │ │ │ ├── minion_druid_of_the_flame.json
│ │ │ │ ├── minion_emperor_thaurissan.json
│ │ │ │ ├── minion_fireguard_destroyer.json
│ │ │ │ ├── minion_flamewaker.json
│ │ │ │ ├── minion_grim_patron.json
│ │ │ │ ├── minion_hungry_dragon.json
│ │ │ │ ├── minion_imp_gang_boss.json
│ │ │ │ ├── minion_majordomo_executus.json
│ │ │ │ ├── minion_nefarian.json
│ │ │ │ ├── minion_rend_blackhand.json
│ │ │ │ ├── minion_twilight_whelp.json
│ │ │ │ ├── minion_volcanic_drake.json
│ │ │ │ ├── minion_volcanic_lumberer.json
│ │ │ │ ├── spell_demonwrath.json
│ │ │ │ ├── spell_dragons_breath.json
│ │ │ │ ├── spell_gang_up.json
│ │ │ │ ├── spell_lava_shock.json
│ │ │ │ ├── spell_quick_shot.json
│ │ │ │ ├── spell_resurrect.json
│ │ │ │ ├── spell_revenge.json
│ │ │ │ ├── spell_solemn_vigil.json
│ │ │ │ ├── spell_tail_swipe.json
│ │ │ │ ├── token_black_whelp.json
│ │ │ │ ├── token_flame_bird_form.json
│ │ │ │ ├── token_flame_lion_form.json
│ │ │ │ └── token_flame_lionbird_form.json
│ │ │ ├── classic/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── minion_ancient_of_lore.json
│ │ │ │ │ ├── minion_ancient_of_war.json
│ │ │ │ │ ├── minion_cenarius.json
│ │ │ │ │ ├── minion_druid_of_the_claw.json
│ │ │ │ │ ├── minion_keeper_of_the_grove.json
│ │ │ │ │ ├── spell_bite.json
│ │ │ │ │ ├── spell_force_of_nature.json
│ │ │ │ │ ├── spell_mark_of_nature.json
│ │ │ │ │ ├── spell_mark_of_nature_1.json
│ │ │ │ │ ├── spell_mark_of_nature_2.json
│ │ │ │ │ ├── spell_mark_of_nature_3.json
│ │ │ │ │ ├── spell_naturalize.json
│ │ │ │ │ ├── spell_nourish.json
│ │ │ │ │ ├── spell_nourish_1.json
│ │ │ │ │ ├── spell_nourish_2.json
│ │ │ │ │ ├── spell_nourish_3.json
│ │ │ │ │ ├── spell_power_of_the_wild.json
│ │ │ │ │ ├── spell_power_of_the_wild_1.json
│ │ │ │ │ ├── spell_power_of_the_wild_2.json
│ │ │ │ │ ├── spell_power_of_the_wild_3.json
│ │ │ │ │ ├── spell_savagery.json
│ │ │ │ │ ├── spell_soul_of_the_forest.json
│ │ │ │ │ ├── spell_starfall.json
│ │ │ │ │ ├── spell_starfall_1.json
│ │ │ │ │ ├── spell_starfall_2.json
│ │ │ │ │ ├── spell_starfall_3.json
│ │ │ │ │ ├── spell_wrath.json
│ │ │ │ │ ├── spell_wrath_1.json
│ │ │ │ │ ├── spell_wrath_2.json
│ │ │ │ │ ├── spell_wrath_3.json
│ │ │ │ │ ├── token_bear_form.json
│ │ │ │ │ ├── token_cat_form.json
│ │ │ │ │ ├── token_catbear_form.json
│ │ │ │ │ ├── token_panther.json
│ │ │ │ │ ├── token_treant.json
│ │ │ │ │ └── token_treant_taunt.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── minion_king_krush.json
│ │ │ │ │ ├── minion_savannah_highmane.json
│ │ │ │ │ ├── minion_scavenging_hyena.json
│ │ │ │ │ ├── secret_explosive_trap.json
│ │ │ │ │ ├── secret_freezing_trap.json
│ │ │ │ │ ├── secret_misdirection.json
│ │ │ │ │ ├── secret_snake_trap.json
│ │ │ │ │ ├── secret_snipe.json
│ │ │ │ │ ├── spell_bestial_wrath.json
│ │ │ │ │ ├── spell_deadly_shot.json
│ │ │ │ │ ├── spell_explosive_shot.json
│ │ │ │ │ ├── spell_flare.json
│ │ │ │ │ ├── spell_unleash_the_hounds.json
│ │ │ │ │ ├── token_hound.json
│ │ │ │ │ ├── token_hyena.json
│ │ │ │ │ ├── token_snake.json
│ │ │ │ │ ├── weapon_eaglehorn_bow.json
│ │ │ │ │ └── weapon_gladiators_longbow.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── minion_archmage_antonidas.json
│ │ │ │ │ ├── minion_ethereal_arcanist.json
│ │ │ │ │ ├── minion_kirin_tor_mage.json
│ │ │ │ │ ├── minion_mana_wyrm.json
│ │ │ │ │ ├── minion_sorcerers_apprentice.json
│ │ │ │ │ ├── secret_counterspell.json
│ │ │ │ │ ├── secret_ice_barrier.json
│ │ │ │ │ ├── secret_ice_block.json
│ │ │ │ │ ├── secret_mirror_entity.json
│ │ │ │ │ ├── secret_spellbender.json
│ │ │ │ │ ├── secret_vaporize.json
│ │ │ │ │ ├── spell_blizzard.json
│ │ │ │ │ ├── spell_cone_of_cold.json
│ │ │ │ │ ├── spell_pyroblast.json
│ │ │ │ │ └── token_spellbender.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_abomination.json
│ │ │ │ │ ├── minion_abusive_sergeant.json
│ │ │ │ │ ├── minion_acolyte_of_pain.json
│ │ │ │ │ ├── minion_alarm-o-bot.json
│ │ │ │ │ ├── minion_alexstrasza.json
│ │ │ │ │ ├── minion_amani_berserker.json
│ │ │ │ │ ├── minion_ancient_brewmaster.json
│ │ │ │ │ ├── minion_ancient_mage.json
│ │ │ │ │ ├── minion_ancient_watcher.json
│ │ │ │ │ ├── minion_angry_chicken.json
│ │ │ │ │ ├── minion_arcane_golem.json
│ │ │ │ │ ├── minion_argent_commander.json
│ │ │ │ │ ├── minion_argent_squire.json
│ │ │ │ │ ├── minion_baron_geddon.json
│ │ │ │ │ ├── minion_big_game_hunter.json
│ │ │ │ │ ├── minion_blood_knight.json
│ │ │ │ │ ├── minion_bloodmage_thalnos.json
│ │ │ │ │ ├── minion_bloodsail_corsair.json
│ │ │ │ │ ├── minion_bloodsail_raider.json
│ │ │ │ │ ├── minion_cairne_bloodhoof.json
│ │ │ │ │ ├── minion_captain_greenskin.json
│ │ │ │ │ ├── minion_coldlight_oracle.json
│ │ │ │ │ ├── minion_coldlight_seer.json
│ │ │ │ │ ├── minion_crazed_alchemist.json
│ │ │ │ │ ├── minion_cult_master.json
│ │ │ │ │ ├── minion_dark_iron_dwarf.json
│ │ │ │ │ ├── minion_deathwing.json
│ │ │ │ │ ├── minion_defender_of_argus.json
│ │ │ │ │ ├── minion_demolisher.json
│ │ │ │ │ ├── minion_dire_wolf_alpha.json
│ │ │ │ │ ├── minion_doomsayer.json
│ │ │ │ │ ├── minion_dread_corsair.json
│ │ │ │ │ ├── minion_earthen_ring_farseer.json
│ │ │ │ │ ├── minion_emperor_cobra.json
│ │ │ │ │ ├── minion_faceless_manipulator.json
│ │ │ │ │ ├── minion_faerie_dragon.json
│ │ │ │ │ ├── minion_fen_creeper.json
│ │ │ │ │ ├── minion_flesheating_ghoul.json
│ │ │ │ │ ├── minion_frost_elemental.json
│ │ │ │ │ ├── minion_gadgetzan_auctioneer.json
│ │ │ │ │ ├── minion_gruul.json
│ │ │ │ │ ├── minion_harrison_jones.json
│ │ │ │ │ ├── minion_harvest_golem.json
│ │ │ │ │ ├── minion_hogger.json
│ │ │ │ │ ├── minion_hungry_crab.json
│ │ │ │ │ ├── minion_illidan_stormrage.json
│ │ │ │ │ ├── minion_imp_master.json
│ │ │ │ │ ├── minion_injured_blademaster.json
│ │ │ │ │ ├── minion_ironbeak_owl.json
│ │ │ │ │ ├── minion_jungle_panther.json
│ │ │ │ │ ├── minion_king_mukla.json
│ │ │ │ │ ├── minion_knife_juggler.json
│ │ │ │ │ ├── minion_leeroy_jenkins.json
│ │ │ │ │ ├── minion_leper_gnome.json
│ │ │ │ │ ├── minion_lightwarden.json
│ │ │ │ │ ├── minion_loot_hoarder.json
│ │ │ │ │ ├── minion_lorewalker_cho.json
│ │ │ │ │ ├── minion_mad_bomber.json
│ │ │ │ │ ├── minion_malygos.json
│ │ │ │ │ ├── minion_mana_addict.json
│ │ │ │ │ ├── minion_mana_wraith.json
│ │ │ │ │ ├── minion_master_swordsmith.json
│ │ │ │ │ ├── minion_millhouse_manastorm.json
│ │ │ │ │ ├── minion_mind_control_tech.json
│ │ │ │ │ ├── minion_mogushan_warden.json
│ │ │ │ │ ├── minion_molten_giant.json
│ │ │ │ │ ├── minion_mountain_giant.json
│ │ │ │ │ ├── minion_murloc_tidecaller.json
│ │ │ │ │ ├── minion_murloc_warleader.json
│ │ │ │ │ ├── minion_nat_pagle.json
│ │ │ │ │ ├── minion_nozdormu.json
│ │ │ │ │ ├── minion_onyxia.json
│ │ │ │ │ ├── minion_pint-sized_summoner.json
│ │ │ │ │ ├── minion_priestess_of_elune.json
│ │ │ │ │ ├── minion_questing_adventurer.json
│ │ │ │ │ ├── minion_raging_worgen.json
│ │ │ │ │ ├── minion_ravenholdt_assassin.json
│ │ │ │ │ ├── minion_scarlet_crusader.json
│ │ │ │ │ ├── minion_sea_giant.json
│ │ │ │ │ ├── minion_secretkeeper.json
│ │ │ │ │ ├── minion_shieldbearer.json
│ │ │ │ │ ├── minion_silver_hand_knight.json
│ │ │ │ │ ├── minion_silvermoon_guardian.json
│ │ │ │ │ ├── minion_southsea_captain.json
│ │ │ │ │ ├── minion_southsea_deckhand.json
│ │ │ │ │ ├── minion_spellbreaker.json
│ │ │ │ │ ├── minion_spiteful_smith.json
│ │ │ │ │ ├── minion_stampeding_kodo.json
│ │ │ │ │ ├── minion_stranglethorn_tiger.json
│ │ │ │ │ ├── minion_sunfury_protector.json
│ │ │ │ │ ├── minion_sunwalker.json
│ │ │ │ │ ├── minion_tauren_warrior.json
│ │ │ │ │ ├── minion_the_beast.json
│ │ │ │ │ ├── minion_the_black_knight.json
│ │ │ │ │ ├── minion_thrallmar_farseer.json
│ │ │ │ │ ├── minion_tinkmaster_overspark.json
│ │ │ │ │ ├── minion_twilight_drake.json
│ │ │ │ │ ├── minion_venture_co_mercenary.json
│ │ │ │ │ ├── minion_violet_teacher.json
│ │ │ │ │ ├── minion_wild_pyromancer.json
│ │ │ │ │ ├── minion_windfury_harpy.json
│ │ │ │ │ ├── minion_wisp.json
│ │ │ │ │ ├── minion_worgen_infiltrator.json
│ │ │ │ │ ├── minion_young_dragonhawk.json
│ │ │ │ │ ├── minion_young_priestess.json
│ │ │ │ │ ├── minion_youthful_brewmaster.json
│ │ │ │ │ ├── minion_ysera.json
│ │ │ │ │ ├── spell_bananas.json
│ │ │ │ │ ├── spell_dream.json
│ │ │ │ │ ├── spell_nightmare.json
│ │ │ │ │ ├── spell_ysera_awakens.json
│ │ │ │ │ ├── token_baine_bloodhoof.json
│ │ │ │ │ ├── token_chicken.json
│ │ │ │ │ ├── token_damaged_golem.json
│ │ │ │ │ ├── token_devilsaur.json
│ │ │ │ │ ├── token_emerald_drake.json
│ │ │ │ │ ├── token_finkle_einhorn.json
│ │ │ │ │ ├── token_flame_of_azzinoth.json
│ │ │ │ │ ├── token_gnoll.json
│ │ │ │ │ ├── token_imp.json
│ │ │ │ │ ├── token_laughing_sister.json
│ │ │ │ │ ├── token_murloc.json
│ │ │ │ │ ├── token_squire.json
│ │ │ │ │ ├── token_squirrel.json
│ │ │ │ │ ├── token_violet_apprentice.json
│ │ │ │ │ └── token_whelp.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── minion_aldor_peacekeeper.json
│ │ │ │ │ ├── minion_argent_protector.json
│ │ │ │ │ ├── minion_tirion_fordring.json
│ │ │ │ │ ├── secret_eye_for_an_eye.json
│ │ │ │ │ ├── secret_noble_sacrifice.json
│ │ │ │ │ ├── secret_redemption.json
│ │ │ │ │ ├── secret_repentance.json
│ │ │ │ │ ├── spell_avenging_wrath.json
│ │ │ │ │ ├── spell_blessed_champion.json
│ │ │ │ │ ├── spell_blessing_of_wisdom.json
│ │ │ │ │ ├── spell_divine_favor.json
│ │ │ │ │ ├── spell_equality.json
│ │ │ │ │ ├── spell_holy_wrath.json
│ │ │ │ │ ├── spell_lay_on_hands.json
│ │ │ │ │ ├── token_defender.json
│ │ │ │ │ ├── weapon_ashbringer.json
│ │ │ │ │ └── weapon_sword_of_justice.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── hero_power_mind_shatter.json
│ │ │ │ │ ├── hero_power_mind_spike.json
│ │ │ │ │ ├── minion_auchenai_soulpriest.json
│ │ │ │ │ ├── minion_cabal_shadow_priest.json
│ │ │ │ │ ├── minion_lightspawn.json
│ │ │ │ │ ├── minion_lightwell.json
│ │ │ │ │ ├── minion_prophet_velen.json
│ │ │ │ │ ├── minion_temple_enforcer.json
│ │ │ │ │ ├── spell_circle_of_healing.json
│ │ │ │ │ ├── spell_holy_fire.json
│ │ │ │ │ ├── spell_inner_fire.json
│ │ │ │ │ ├── spell_mass_dispel.json
│ │ │ │ │ ├── spell_mindgames.json
│ │ │ │ │ ├── spell_shadow_madness.json
│ │ │ │ │ ├── spell_shadowform.json
│ │ │ │ │ ├── spell_silence.json
│ │ │ │ │ ├── spell_thoughtsteal.json
│ │ │ │ │ └── token_shadow_of_nothing.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── minion_defias_ringleader.json
│ │ │ │ │ ├── minion_edwin_vancleef.json
│ │ │ │ │ ├── minion_kidnapper.json
│ │ │ │ │ ├── minion_master_of_disguise.json
│ │ │ │ │ ├── minion_patient_assassin.json
│ │ │ │ │ ├── minion_si7_agent.json
│ │ │ │ │ ├── spell_betrayal.json
│ │ │ │ │ ├── spell_blade_flurry.json
│ │ │ │ │ ├── spell_cold_blood.json
│ │ │ │ │ ├── spell_eviscerate.json
│ │ │ │ │ ├── spell_headcrack.json
│ │ │ │ │ ├── spell_preparation.json
│ │ │ │ │ ├── spell_shadowstep.json
│ │ │ │ │ ├── token_defias_bandit.json
│ │ │ │ │ └── weapon_perditions_blade.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── minion_al_akir_the_windlord.json
│ │ │ │ │ ├── minion_dust_devil.json
│ │ │ │ │ ├── minion_earth_elemental.json
│ │ │ │ │ ├── minion_mana_tide_totem.json
│ │ │ │ │ ├── minion_unbound_elemental.json
│ │ │ │ │ ├── spell_ancestral_spirit.json
│ │ │ │ │ ├── spell_earth_shock.json
│ │ │ │ │ ├── spell_far_sight.json
│ │ │ │ │ ├── spell_feral_spirit.json
│ │ │ │ │ ├── spell_forked_lightning.json
│ │ │ │ │ ├── spell_lava_burst.json
│ │ │ │ │ ├── spell_lightning_bolt.json
│ │ │ │ │ ├── spell_lightning_storm.json
│ │ │ │ │ ├── token_spirit_wolf.json
│ │ │ │ │ ├── weapon_doomhammer.json
│ │ │ │ │ └── weapon_stormforged_axe.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── hero_jaraxxus.json
│ │ │ │ │ ├── hero_power_inferno.json
│ │ │ │ │ ├── minion_blood_imp.json
│ │ │ │ │ ├── minion_doomguard.json
│ │ │ │ │ ├── minion_felguard.json
│ │ │ │ │ ├── minion_flame_imp.json
│ │ │ │ │ ├── minion_lord_jaraxxus.json
│ │ │ │ │ ├── minion_pit_lord.json
│ │ │ │ │ ├── minion_summoning_portal.json
│ │ │ │ │ ├── minion_void_terror.json
│ │ │ │ │ ├── spell_bane_of_doom.json
│ │ │ │ │ ├── spell_demonfire.json
│ │ │ │ │ ├── spell_sense_demons.json
│ │ │ │ │ ├── spell_shadowflame.json
│ │ │ │ │ ├── spell_siphon_soul.json
│ │ │ │ │ ├── spell_twisting_nether.json
│ │ │ │ │ ├── token_infernal.json
│ │ │ │ │ ├── token_worthless_imp.json
│ │ │ │ │ └── weapon_blood_fury.json
│ │ │ │ └── warrior/
│ │ │ │ ├── minion_arathi_weaponsmith.json
│ │ │ │ ├── minion_armorsmith.json
│ │ │ │ ├── minion_cruel_taskmaster.json
│ │ │ │ ├── minion_frothing_berserker.json
│ │ │ │ ├── minion_grommash_hellscream.json
│ │ │ │ ├── spell_battle_rage.json
│ │ │ │ ├── spell_brawl.json
│ │ │ │ ├── spell_commanding_shout.json
│ │ │ │ ├── spell_inner_rage.json
│ │ │ │ ├── spell_mortal_strike.json
│ │ │ │ ├── spell_rampage.json
│ │ │ │ ├── spell_shield_slam.json
│ │ │ │ ├── spell_slam.json
│ │ │ │ ├── spell_upgrade.json
│ │ │ │ ├── weapon_battle_axe.json
│ │ │ │ ├── weapon_gorehowl.json
│ │ │ │ └── weapon_heavy_axe.json
│ │ │ ├── goblins_vs_gnomes/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── minion_anodized_robo_cub.json
│ │ │ │ │ ├── minion_druid_of_the_fang.json
│ │ │ │ │ ├── minion_grove_tender.json
│ │ │ │ │ ├── minion_malorne.json
│ │ │ │ │ ├── minion_mech-bear-cat.json
│ │ │ │ │ ├── spell_dark_wispers.json
│ │ │ │ │ ├── spell_dark_wispers_1.json
│ │ │ │ │ ├── spell_dark_wispers_2.json
│ │ │ │ │ ├── spell_dark_wispers_3.json
│ │ │ │ │ ├── spell_recycle.json
│ │ │ │ │ ├── spell_tree_of_life.json
│ │ │ │ │ └── token_cobra_form.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── minion_gahzrilla.json
│ │ │ │ │ ├── minion_king_of_beasts.json
│ │ │ │ │ ├── minion_metaltooth_leaper.json
│ │ │ │ │ ├── minion_steamwheedle_sniper.json
│ │ │ │ │ ├── spell_call_pet.json
│ │ │ │ │ ├── spell_cobra_shot.json
│ │ │ │ │ ├── spell_feign_death.json
│ │ │ │ │ └── weapon_glaivezooka.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── minion_flame_leviathan.json
│ │ │ │ │ ├── minion_goblin_blastmage.json
│ │ │ │ │ ├── minion_snowchugger.json
│ │ │ │ │ ├── minion_soot_spewer.json
│ │ │ │ │ ├── minion_wee_spellstopper.json
│ │ │ │ │ ├── spell_echo_of_medivh.json
│ │ │ │ │ ├── spell_flamecannon.json
│ │ │ │ │ └── spell_unstable_portal.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_annoy-o-tron.json
│ │ │ │ │ ├── minion_antique_healbot.json
│ │ │ │ │ ├── minion_arcane_nullifier_x-21.json
│ │ │ │ │ ├── minion_blingtron_3000.json
│ │ │ │ │ ├── minion_bomb_lobber.json
│ │ │ │ │ ├── minion_burly_rockjaw_trogg.json
│ │ │ │ │ ├── minion_clockwork_giant.json
│ │ │ │ │ ├── minion_clockwork_gnome.json
│ │ │ │ │ ├── minion_cogmaster.json
│ │ │ │ │ ├── minion_dr_boom.json
│ │ │ │ │ ├── minion_enhance-o_mechano.json
│ │ │ │ │ ├── minion_explosive_sheep.json
│ │ │ │ │ ├── minion_fel_reaver.json
│ │ │ │ │ ├── minion_flying_machine.json
│ │ │ │ │ ├── minion_foe_reaper_4000.json
│ │ │ │ │ ├── minion_force-tank_max.json
│ │ │ │ │ ├── minion_gazlowe.json
│ │ │ │ │ ├── minion_gilblin_stalker.json
│ │ │ │ │ ├── minion_gnomeregan_infantry.json
│ │ │ │ │ ├── minion_gnomish_experimenter.json
│ │ │ │ │ ├── minion_goblin_sapper.json
│ │ │ │ │ ├── minion_hemet_nesingwary.json
│ │ │ │ │ ├── minion_hobgoblin.json
│ │ │ │ │ ├── minion_illuminator.json
│ │ │ │ │ ├── minion_jeeves.json
│ │ │ │ │ ├── minion_junkbot.json
│ │ │ │ │ ├── minion_kezan_mystic.json
│ │ │ │ │ ├── minion_lil_exorcist.json
│ │ │ │ │ ├── minion_lost_tallstrider.json
│ │ │ │ │ ├── minion_madder_bomber.json
│ │ │ │ │ ├── minion_mechanical_yeti.json
│ │ │ │ │ ├── minion_mechwarper.json
│ │ │ │ │ ├── minion_mekgineer_thermaplugg.json
│ │ │ │ │ ├── minion_micro_machine.json
│ │ │ │ │ ├── minion_mimirons_head.json
│ │ │ │ │ ├── minion_mini-mage.json
│ │ │ │ │ ├── minion_mogor_the_ogre.json
│ │ │ │ │ ├── minion_ogre_brute.json
│ │ │ │ │ ├── minion_piloted_shredder.json
│ │ │ │ │ ├── minion_piloted_sky_golem.json
│ │ │ │ │ ├── minion_puddlestomper.json
│ │ │ │ │ ├── minion_recombobulator.json
│ │ │ │ │ ├── minion_salty_dog.json
│ │ │ │ │ ├── minion_ships_cannon.json
│ │ │ │ │ ├── minion_sneeds_old_shredder.json
│ │ │ │ │ ├── minion_spider_tank.json
│ │ │ │ │ ├── minion_stonesplinter_trogg.json
│ │ │ │ │ ├── minion_target_dummy.json
│ │ │ │ │ ├── minion_tinkertown_technician.json
│ │ │ │ │ ├── minion_toshley.json
│ │ │ │ │ ├── minion_troggzor_the_earthinator.json
│ │ │ │ │ ├── token_boom_bot.json
│ │ │ │ │ ├── token_chicken_gvg.json
│ │ │ │ │ └── token_v-07-tr-0n.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── minion_bolvar_fordragon.json
│ │ │ │ │ ├── minion_cobalt_guardian.json
│ │ │ │ │ ├── minion_quartermaster.json
│ │ │ │ │ ├── minion_scarlet_purifier.json
│ │ │ │ │ ├── minion_shielded_minibot.json
│ │ │ │ │ ├── spell_muster_for_battle.json
│ │ │ │ │ ├── spell_seal_of_light.json
│ │ │ │ │ └── weapon_coghammer.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── minion_shadowbomber.json
│ │ │ │ │ ├── minion_shadowboxer.json
│ │ │ │ │ ├── minion_shrinkmeister.json
│ │ │ │ │ ├── minion_upgraded_repair_bot.json
│ │ │ │ │ ├── minion_voljin.json
│ │ │ │ │ ├── spell_light_of_the_naaru.json
│ │ │ │ │ ├── spell_lightbomb.json
│ │ │ │ │ └── spell_velens_chosen.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── minion_goblin_auto-barber.json
│ │ │ │ │ ├── minion_iron_sensei.json
│ │ │ │ │ ├── minion_ogre_ninja.json
│ │ │ │ │ ├── minion_one-eyed_cheat.json
│ │ │ │ │ ├── minion_trade_prince_gallywix.json
│ │ │ │ │ ├── spell_gallywixs_coin.json
│ │ │ │ │ ├── spell_sabotage.json
│ │ │ │ │ ├── spell_tinkers_sharpsword_oil.json
│ │ │ │ │ └── weapon_cogmasters_wrench.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── minion_dunemaul_shaman.json
│ │ │ │ │ ├── minion_neptulon.json
│ │ │ │ │ ├── minion_siltfin_spiritwalker.json
│ │ │ │ │ ├── minion_vitality_totem.json
│ │ │ │ │ ├── minion_whirling_zap-o-matic.json
│ │ │ │ │ ├── spell_ancestors_call.json
│ │ │ │ │ ├── spell_crackle.json
│ │ │ │ │ └── weapon_powermace.json
│ │ │ │ ├── spare_parts/
│ │ │ │ │ ├── spell_armor_plating.json
│ │ │ │ │ ├── spell_emergency_coolant.json
│ │ │ │ │ ├── spell_finicky_cloakfield.json
│ │ │ │ │ ├── spell_reversing_switch.json
│ │ │ │ │ ├── spell_rusty_horn.json
│ │ │ │ │ ├── spell_time_rewinder.json
│ │ │ │ │ └── spell_whirling_blades.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── minion_anima_golem.json
│ │ │ │ │ ├── minion_fel_cannon.json
│ │ │ │ │ ├── minion_floating_watcher.json
│ │ │ │ │ ├── minion_malganis.json
│ │ │ │ │ ├── minion_mistress_of_pain.json
│ │ │ │ │ ├── spell_darkbomb.json
│ │ │ │ │ ├── spell_demonheart.json
│ │ │ │ │ └── spell_imp-losion.json
│ │ │ │ └── warrior/
│ │ │ │ ├── minion_iron_juggernaut.json
│ │ │ │ ├── minion_screwjank_clunker.json
│ │ │ │ ├── minion_shieldmaiden.json
│ │ │ │ ├── minion_siege_engine.json
│ │ │ │ ├── minion_warbot.json
│ │ │ │ ├── spell_bouncing_blade.json
│ │ │ │ ├── spell_burrowing_mine.json
│ │ │ │ ├── spell_crush.json
│ │ │ │ └── weapon_ogre_warmaul.json
│ │ │ ├── hall_of_fame/
│ │ │ │ ├── minion_azure_drake.json
│ │ │ │ ├── minion_captains_parrot.json
│ │ │ │ ├── minion_elite_tauren_chieftain.json
│ │ │ │ ├── minion_gelbin_mekkatorque.json
│ │ │ │ ├── minion_old_murk-eye.json
│ │ │ │ ├── minion_ragnaros_the_firelord.json
│ │ │ │ ├── minion_sylvanas_windrunner.json
│ │ │ │ ├── spell_conceal.json
│ │ │ │ ├── spell_ice_lance.json
│ │ │ │ └── spell_power_overwhelming.json
│ │ │ ├── league_of_explorers/
│ │ │ │ ├── minion_ancient_shade.json
│ │ │ │ ├── minion_animated_armor.json
│ │ │ │ ├── minion_anubisath_sentinel.json
│ │ │ │ ├── minion_archthief_rafaam.json
│ │ │ │ ├── minion_brann_bronzebeard.json
│ │ │ │ ├── minion_dark_peddler.json
│ │ │ │ ├── minion_desert_camel.json
│ │ │ │ ├── minion_djinni_of_zephyrs.json
│ │ │ │ ├── minion_eerie_statue.json
│ │ │ │ ├── minion_elise_starseeker.json
│ │ │ │ ├── minion_ethereal_conjurer.json
│ │ │ │ ├── minion_fierce_monkey.json
│ │ │ │ ├── minion_fossilized_devilsaur.json
│ │ │ │ ├── minion_gorillabot_a3.json
│ │ │ │ ├── minion_huge_toad.json
│ │ │ │ ├── minion_jeweled_scarab.json
│ │ │ │ ├── minion_jungle_moonkin.json
│ │ │ │ ├── minion_keeper_of_uldaman.json
│ │ │ │ ├── minion_mounted_raptor.json
│ │ │ │ ├── minion_murloc_tinyfin.json
│ │ │ │ ├── minion_museum_curator.json
│ │ │ │ ├── minion_naga_sea_witch.json
│ │ │ │ ├── minion_obsidian_destroyer.json
│ │ │ │ ├── minion_pit_snake.json
│ │ │ │ ├── minion_reliquary_seeker.json
│ │ │ │ ├── minion_reno_jackson.json
│ │ │ │ ├── minion_rumbling_elemental.json
│ │ │ │ ├── minion_sir_finley_mrrgglton.json
│ │ │ │ ├── minion_summoning_stone.json
│ │ │ │ ├── minion_tomb_pillager.json
│ │ │ │ ├── minion_tomb_spider.json
│ │ │ │ ├── minion_tunnel_trogg.json
│ │ │ │ ├── minion_unearthed_raptor.json
│ │ │ │ ├── minion_wobbling_runts.json
│ │ │ │ ├── secret_dart_trap.json
│ │ │ │ ├── secret_sacred_trial.json
│ │ │ │ ├── spell_ancient_curse.json
│ │ │ │ ├── spell_anyfin_can_happen.json
│ │ │ │ ├── spell_curse_of_rafaam.json
│ │ │ │ ├── spell_cursed.json
│ │ │ │ ├── spell_entomb.json
│ │ │ │ ├── spell_everyfin_is_awesome.json
│ │ │ │ ├── spell_excavated_evil.json
│ │ │ │ ├── spell_explorers_hat.json
│ │ │ │ ├── spell_forgotten_torch.json
│ │ │ │ ├── spell_lantern_of_power.json
│ │ │ │ ├── spell_map_to_the_golden_monkey.json
│ │ │ │ ├── spell_mirror_of_doom.json
│ │ │ │ ├── spell_raven_idol.json
│ │ │ │ ├── spell_raven_idol_1.json
│ │ │ │ ├── spell_raven_idol_2.json
│ │ │ │ ├── spell_raven_idol_3.json
│ │ │ │ ├── spell_roaring_torch.json
│ │ │ │ ├── spell_timepiece_of_horror.json
│ │ │ │ ├── token_golden_monkey.json
│ │ │ │ ├── token_grumbly_runt.json
│ │ │ │ ├── token_mummy_zombie.json
│ │ │ │ ├── token_rascally_runt.json
│ │ │ │ ├── token_scarab.json
│ │ │ │ ├── token_wily_runt.json
│ │ │ │ └── weapon_cursed_blade.json
│ │ │ ├── mean_streets_of_gadgetzan/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── minion_celestial_dreamer.json
│ │ │ │ │ ├── minion_jade_behemoth.json
│ │ │ │ │ ├── minion_kun_the_forgotten_king.json
│ │ │ │ │ ├── minion_virmen_sensei.json
│ │ │ │ │ ├── spell_jade_blossom.json
│ │ │ │ │ ├── spell_jade_idol.json
│ │ │ │ │ ├── spell_jade_idol_1.json
│ │ │ │ │ ├── spell_jade_idol_2.json
│ │ │ │ │ ├── spell_jade_idol_3.json
│ │ │ │ │ ├── spell_lunar_visions.json
│ │ │ │ │ ├── spell_mark_of_the_lotus.json
│ │ │ │ │ └── spell_pilfered_power.json
│ │ │ │ ├── grimy_goons/
│ │ │ │ │ ├── minion_don_hancho.json
│ │ │ │ │ ├── minion_grimestreet_informant.json
│ │ │ │ │ └── minion_grimestreet_smuggler.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── minion_alleycat.json
│ │ │ │ │ ├── minion_dispatch_kodo.json
│ │ │ │ │ ├── minion_knuckles.json
│ │ │ │ │ ├── minion_rat_pack.json
│ │ │ │ │ ├── minion_shaky_zipgunner.json
│ │ │ │ │ ├── minion_trogg_beastrager.json
│ │ │ │ │ ├── secret_hidden_cache.json
│ │ │ │ │ ├── spell_smugglers_crate.json
│ │ │ │ │ ├── token_piranha.json
│ │ │ │ │ ├── token_rat.json
│ │ │ │ │ ├── token_tabbycat.json
│ │ │ │ │ └── weapon_piranha_launcher.json
│ │ │ │ ├── jade_lotus/
│ │ │ │ │ ├── minion_aya_blackpaw.json
│ │ │ │ │ ├── minion_jade_spirit.json
│ │ │ │ │ └── minion_lotus_agents.json
│ │ │ │ ├── kabal/
│ │ │ │ │ ├── minion_kabal_chemist.json
│ │ │ │ │ ├── minion_kabal_courier.json
│ │ │ │ │ ├── minion_kazakus.json
│ │ │ │ │ ├── token_greater_demon.json
│ │ │ │ │ ├── token_kabal_sheep.json
│ │ │ │ │ ├── token_lesser_demon.json
│ │ │ │ │ └── token_superior_demon.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── hero_baaraxxus.json
│ │ │ │ │ ├── minion_cryomancer.json
│ │ │ │ │ ├── minion_inkmaster_solia.json
│ │ │ │ │ ├── minion_kabal_crystal_runner.json
│ │ │ │ │ ├── minion_kabal_lackey.json
│ │ │ │ │ ├── minion_manic_soulcaster.json
│ │ │ │ │ ├── secret_potion_of_polymorph.json
│ │ │ │ │ ├── spell_freezing_potion.json
│ │ │ │ │ ├── spell_greater_arcane_missiles.json
│ │ │ │ │ └── spell_volcanic_potion.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_ancient_of_blossoms.json
│ │ │ │ │ ├── minion_auctionmaster_beardo.json
│ │ │ │ │ ├── minion_backroom_bouncer.json
│ │ │ │ │ ├── minion_backstreet_leper.json
│ │ │ │ │ ├── minion_big-time_racketeer.json
│ │ │ │ │ ├── minion_blowgill_sniper.json
│ │ │ │ │ ├── minion_blubber_baron.json
│ │ │ │ │ ├── minion_bomb_squad.json
│ │ │ │ │ ├── minion_burgly_bully.json
│ │ │ │ │ ├── minion_daring_reporter.json
│ │ │ │ │ ├── minion_defias_cleaner.json
│ │ │ │ │ ├── minion_dirty_rat.json
│ │ │ │ │ ├── minion_doppelgangster.json
│ │ │ │ │ ├── minion_fel_orc_soulfiend.json
│ │ │ │ │ ├── minion_fight_promoter.json
│ │ │ │ │ ├── minion_finja_the_flying_star.json
│ │ │ │ │ ├── minion_friendly_bartender.json
│ │ │ │ │ ├── minion_gadgetzan_socialite.json
│ │ │ │ │ ├── minion_genzo_the_shark.json
│ │ │ │ │ ├── minion_grook_fu_master.json
│ │ │ │ │ ├── minion_hired_gun.json
│ │ │ │ │ ├── minion_hozen_healer.json
│ │ │ │ │ ├── minion_kooky_chemist.json
│ │ │ │ │ ├── minion_leatherclad_hogleader.json
│ │ │ │ │ ├── minion_madam_goya.json
│ │ │ │ │ ├── minion_mayor_noggenfogger.json
│ │ │ │ │ ├── minion_mistress_of_mixtures.json
│ │ │ │ │ ├── minion_naga_corsair.json
│ │ │ │ │ ├── minion_patches_the_pirate.json
│ │ │ │ │ ├── minion_red_mana_wyrm.json
│ │ │ │ │ ├── minion_second-rate_bruiser.json
│ │ │ │ │ ├── minion_sergeant_sally.json
│ │ │ │ │ ├── minion_small-time_buccaneer.json
│ │ │ │ │ ├── minion_spiked_hogrider.json
│ │ │ │ │ ├── minion_street_trickster.json
│ │ │ │ │ ├── minion_streetwise_investigator.json
│ │ │ │ │ ├── minion_tanaris_hogchopper.json
│ │ │ │ │ ├── minion_toxic_sewer_ooze.json
│ │ │ │ │ ├── minion_weasel_tunneler.json
│ │ │ │ │ ├── minion_wind-up_burglebot.json
│ │ │ │ │ ├── minion_worgen_greaser.json
│ │ │ │ │ ├── minion_wrathion.json
│ │ │ │ │ └── token_ogre.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── minion_grimestreet_enforcer.json
│ │ │ │ │ ├── minion_grimestreet_outfitter.json
│ │ │ │ │ ├── minion_grimestreet_protector.json
│ │ │ │ │ ├── minion_grimscale_chum.json
│ │ │ │ │ ├── minion_meanstreet_marshal.json
│ │ │ │ │ ├── minion_wickerflame_burnbirstle.json
│ │ │ │ │ ├── secret_getaway_kodo.json
│ │ │ │ │ ├── spell_small-time_recruits.json
│ │ │ │ │ └── spell_smugglers_run.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── minion_drakonid_operative.json
│ │ │ │ │ ├── minion_kabal_songstealer.json
│ │ │ │ │ ├── minion_kabal_talonpriest.json
│ │ │ │ │ ├── minion_mana_geode.json
│ │ │ │ │ ├── minion_raza_the_chained.json
│ │ │ │ │ ├── spell_dragonfire_potion.json
│ │ │ │ │ ├── spell_greater_healing_potion.json
│ │ │ │ │ ├── spell_pint-size_potion.json
│ │ │ │ │ ├── spell_potion_of_madness.json
│ │ │ │ │ └── token_crystal.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── minion_gadgetzan_ferryman.json
│ │ │ │ │ ├── minion_jade_swarmer.json
│ │ │ │ │ ├── minion_lotus_assassin.json
│ │ │ │ │ ├── minion_luckydo_buccaneer.json
│ │ │ │ │ ├── minion_shadow_rager.json
│ │ │ │ │ ├── minion_shadow_sensei.json
│ │ │ │ │ ├── minion_shaku_the_collector.json
│ │ │ │ │ ├── spell_counterfeit_coin.json
│ │ │ │ │ └── spell_jade_shuriken.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── minion_jade_chieftain.json
│ │ │ │ │ ├── minion_jinyu_waterspeaker.json
│ │ │ │ │ ├── minion_lotus_illusionist.json
│ │ │ │ │ ├── minion_white_eyes.json
│ │ │ │ │ ├── spell_call_in_the_finishers.json
│ │ │ │ │ ├── spell_devolve.json
│ │ │ │ │ ├── spell_finders_keepers.json
│ │ │ │ │ ├── spell_jade_lightning.json
│ │ │ │ │ ├── token_murloc_razorgill.json
│ │ │ │ │ ├── token_the_storm_guardian.json
│ │ │ │ │ └── weapon_jade_claws.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── minion_abyssal_enforcer.json
│ │ │ │ │ ├── minion_crystalweaver.json
│ │ │ │ │ ├── minion_kabal_trafficker.json
│ │ │ │ │ ├── minion_krul_the_unshackled.json
│ │ │ │ │ ├── minion_seadevil_stinger.json
│ │ │ │ │ ├── minion_unlicensed_apothecary.json
│ │ │ │ │ ├── spell_blastcrystal_potion.json
│ │ │ │ │ ├── spell_bloodfury_potion.json
│ │ │ │ │ └── spell_felfire_potion.json
│ │ │ │ └── warrior/
│ │ │ │ ├── minion_alley_armorsmith.json
│ │ │ │ ├── minion_grimestreet_pawnbroker.json
│ │ │ │ ├── minion_grimy_gadgeteer.json
│ │ │ │ ├── minion_hobart_grapplehammer.json
│ │ │ │ ├── minion_public_defender.json
│ │ │ │ ├── spell_i_know_a_guy.json
│ │ │ │ ├── spell_sleep_with_the_fishes.json
│ │ │ │ ├── spell_stolen_goods.json
│ │ │ │ └── weapon_brass_knuckles.json
│ │ │ ├── naxxramas/
│ │ │ │ ├── minion_anubar_ambusher.json
│ │ │ │ ├── minion_baron_rivendare.json
│ │ │ │ ├── minion_dancing_swords.json
│ │ │ │ ├── minion_dark_cultist.json
│ │ │ │ ├── minion_deathlord.json
│ │ │ │ ├── minion_echoing_ooze.json
│ │ │ │ ├── minion_feugen.json
│ │ │ │ ├── minion_haunted_creeper.json
│ │ │ │ ├── minion_kelthuzad.json
│ │ │ │ ├── minion_loatheb.json
│ │ │ │ ├── minion_mad_scientist.json
│ │ │ │ ├── minion_maexxna.json
│ │ │ │ ├── minion_nerubar_weblord.json
│ │ │ │ ├── minion_nerubian_egg.json
│ │ │ │ ├── minion_shade_of_naxxramas.json
│ │ │ │ ├── minion_sludge_belcher.json
│ │ │ │ ├── minion_spectral_knight.json
│ │ │ │ ├── minion_stalagg.json
│ │ │ │ ├── minion_stoneskin_gargoyle.json
│ │ │ │ ├── minion_undertaker.json
│ │ │ │ ├── minion_unstable_ghoul.json
│ │ │ │ ├── minion_voidcaller.json
│ │ │ │ ├── minion_wailing_soul.json
│ │ │ │ ├── minion_webspinner.json
│ │ │ │ ├── minion_zombie_chow.json
│ │ │ │ ├── secret_avenge.json
│ │ │ │ ├── secret_duplicate.json
│ │ │ │ ├── spell_poison_seeds.json
│ │ │ │ ├── spell_reincarnate.json
│ │ │ │ ├── token_nerubian.json
│ │ │ │ ├── token_slime.json
│ │ │ │ ├── token_spectral_spider.json
│ │ │ │ ├── token_thaddius.json
│ │ │ │ └── weapon_deaths_bite.json
│ │ │ ├── one_night_in_karazhan/
│ │ │ │ ├── minion_arcane_anomaly.json
│ │ │ │ ├── minion_arcane_giant.json
│ │ │ │ ├── minion_arcanosmith.json
│ │ │ │ ├── minion_avian_watcher.json
│ │ │ │ ├── minion_babbling_book.json
│ │ │ │ ├── minion_barnes.json
│ │ │ │ ├── minion_book_wyrm.json
│ │ │ │ ├── minion_cloaked_huntress.json
│ │ │ │ ├── minion_deadly_fork.json
│ │ │ │ ├── minion_enchanted_raven.json
│ │ │ │ ├── minion_ethereal_peddler.json
│ │ │ │ ├── minion_ivory_knight.json
│ │ │ │ ├── minion_kindly_grandmother.json
│ │ │ │ ├── minion_malchezaars_imp.json
│ │ │ │ ├── minion_medivh_the_guardian.json
│ │ │ │ ├── minion_medivhs_valet.json
│ │ │ │ ├── minion_menagerie_magician.json
│ │ │ │ ├── minion_menagerie_warden.json
│ │ │ │ ├── minion_moat_lurker.json
│ │ │ │ ├── minion_moroes.json
│ │ │ │ ├── minion_netherspite_historian.json
│ │ │ │ ├── minion_nightbane_templar.json
│ │ │ │ ├── minion_onyx_bishop.json
│ │ │ │ ├── minion_pantry_spider.json
│ │ │ │ ├── minion_pompous_thespian.json
│ │ │ │ ├── minion_priest_of_the_feast.json
│ │ │ │ ├── minion_prince_malchezaar.json
│ │ │ │ ├── minion_runic_egg.json
│ │ │ │ ├── minion_silverware_golem.json
│ │ │ │ ├── minion_swashburglar.json
│ │ │ │ ├── minion_the_curator.json
│ │ │ │ ├── minion_violet_illusionist.json
│ │ │ │ ├── minion_wicked_witchdoctor.json
│ │ │ │ ├── minion_zoobot.json
│ │ │ │ ├── secret_cat_trick.json
│ │ │ │ ├── spell_firelands_portal.json
│ │ │ │ ├── spell_ironforge_portal.json
│ │ │ │ ├── spell_kara_kazham.json
│ │ │ │ ├── spell_maelstrom_portal.json
│ │ │ │ ├── spell_moonglade_portal.json
│ │ │ │ ├── spell_protect_the_king.json
│ │ │ │ ├── spell_purify.json
│ │ │ │ ├── spell_silvermoon_portal.json
│ │ │ │ ├── token_animated_shield.json
│ │ │ │ ├── token_big_bad_wolf.json
│ │ │ │ ├── token_broom.json
│ │ │ │ ├── token_candle.json
│ │ │ │ ├── token_cat_in_a_hat.json
│ │ │ │ ├── token_cellar_spider.json
│ │ │ │ ├── token_pawn.json
│ │ │ │ ├── token_steward.json
│ │ │ │ ├── token_teapot.json
│ │ │ │ ├── weapon_atiesh.json
│ │ │ │ ├── weapon_fools_bane.json
│ │ │ │ ├── weapon_sharp_fork.json
│ │ │ │ └── weapon_spirit_claws.json
│ │ │ ├── promo/
│ │ │ │ ├── spell_i_am_murloc.json
│ │ │ │ ├── spell_power_of_the_horde.json
│ │ │ │ ├── spell_rogues_do_it.json
│ │ │ │ ├── token_emboldener_3000.json
│ │ │ │ ├── token_homing_chicken.json
│ │ │ │ ├── token_poultryizer.json
│ │ │ │ └── token_repair_bot.json
│ │ │ ├── the_grand_tournament/
│ │ │ │ ├── druid/
│ │ │ │ │ ├── hero_power_dire_shapeshift.json
│ │ │ │ │ ├── minion_aviana.json
│ │ │ │ │ ├── minion_darnassus_aspirant.json
│ │ │ │ │ ├── minion_druid_of_the_saber.json
│ │ │ │ │ ├── minion_knight_of_the_wild.json
│ │ │ │ │ ├── minion_savage_combatant.json
│ │ │ │ │ ├── minion_wildwalker.json
│ │ │ │ │ ├── spell_astral_communion.json
│ │ │ │ │ ├── spell_living_roots.json
│ │ │ │ │ ├── spell_living_roots_1.json
│ │ │ │ │ ├── spell_living_roots_2.json
│ │ │ │ │ ├── spell_living_roots_3.json
│ │ │ │ │ ├── spell_mulch.json
│ │ │ │ │ ├── token_sabertooth_lion.json
│ │ │ │ │ ├── token_sabertooth_panther.json
│ │ │ │ │ ├── token_sabertooth_tiger.json
│ │ │ │ │ └── token_sapling.json
│ │ │ │ ├── hunter/
│ │ │ │ │ ├── hero_power_ballista_shot.json
│ │ │ │ │ ├── minion_acidmaw.json
│ │ │ │ │ ├── minion_brave_archer.json
│ │ │ │ │ ├── minion_dreadscale.json
│ │ │ │ │ ├── minion_kings_elekk.json
│ │ │ │ │ ├── minion_ram_wrangler.json
│ │ │ │ │ ├── minion_stablemaster.json
│ │ │ │ │ ├── secret_bear_trap.json
│ │ │ │ │ ├── spell_ball_of_spiders.json
│ │ │ │ │ ├── spell_lock_and_load.json
│ │ │ │ │ └── spell_powershot.json
│ │ │ │ ├── mage/
│ │ │ │ │ ├── hero_power_fireblast_rank_2.json
│ │ │ │ │ ├── minion_coldarra_drake.json
│ │ │ │ │ ├── minion_dalaran_aspirant.json
│ │ │ │ │ ├── minion_fallen_hero.json
│ │ │ │ │ ├── minion_rhonin.json
│ │ │ │ │ ├── minion_spellslinger.json
│ │ │ │ │ ├── secret_effigy.json
│ │ │ │ │ ├── spell_arcane_blast.json
│ │ │ │ │ ├── spell_flame_lance.json
│ │ │ │ │ ├── spell_polymorph_boar.json
│ │ │ │ │ └── token_mage_huffer.json
│ │ │ │ ├── neutral/
│ │ │ │ │ ├── minion_argent_horserider.json
│ │ │ │ │ ├── minion_argent_watchman.json
│ │ │ │ │ ├── minion_armored_warhorse.json
│ │ │ │ │ ├── minion_bolf_ramshield.json
│ │ │ │ │ ├── minion_boneguard_lieutenant.json
│ │ │ │ │ ├── minion_captured_jormungar.json
│ │ │ │ │ ├── minion_chillmaw.json
│ │ │ │ │ ├── minion_clockwork_knight.json
│ │ │ │ │ ├── minion_coliseum_manager.json
│ │ │ │ │ ├── minion_crowd_favorite.json
│ │ │ │ │ ├── minion_dragonhawk_rider.json
│ │ │ │ │ ├── minion_evil_heckler.json
│ │ │ │ │ ├── minion_eydis_darkbane.json
│ │ │ │ │ ├── minion_fencing_coach.json
│ │ │ │ │ ├── minion_fjola_lightbane.json
│ │ │ │ │ ├── minion_flame_juggler.json
│ │ │ │ │ ├── minion_frigid_snobold.json
│ │ │ │ │ ├── minion_frost_giant.json
│ │ │ │ │ ├── minion_gadgetzan_jouster.json
│ │ │ │ │ ├── minion_garrison_commander.json
│ │ │ │ │ ├── minion_gormok_the_impaler.json
│ │ │ │ │ ├── minion_grand_crusader.json
│ │ │ │ │ ├── minion_ice_rager.json
│ │ │ │ │ ├── minion_icehowl.json
│ │ │ │ │ ├── minion_injured_kvaldir.json
│ │ │ │ │ ├── minion_justicar_trueheart.json
│ │ │ │ │ ├── minion_kodorider.json
│ │ │ │ │ ├── minion_kvaldir_raider.json
│ │ │ │ │ ├── minion_lance_carrier.json
│ │ │ │ │ ├── minion_lights_champion.json
│ │ │ │ │ ├── minion_lowly_squire.json
│ │ │ │ │ ├── minion_maiden_of_the_lake.json
│ │ │ │ │ ├── minion_master_jouster.json
│ │ │ │ │ ├── minion_master_of_ceremonies.json
│ │ │ │ │ ├── minion_mogors_champion.json
│ │ │ │ │ ├── minion_muklas_champion.json
│ │ │ │ │ ├── minion_nexus-champion_saraad.json
│ │ │ │ │ ├── minion_north_sea_kraken.json
│ │ │ │ │ ├── minion_pit_fighter.json
│ │ │ │ │ ├── minion_recruiter.json
│ │ │ │ │ ├── minion_refreshment_vendor.json
│ │ │ │ │ ├── minion_saboteur.json
│ │ │ │ │ ├── minion_sideshow_spelleater.json
│ │ │ │ │ ├── minion_silent_knight.json
│ │ │ │ │ ├── minion_silver_hand_regent.json
│ │ │ │ │ ├── minion_skycapn_kragg.json
│ │ │ │ │ ├── minion_the_skeleton_knight.json
│ │ │ │ │ ├── minion_tournament_attendee.json
│ │ │ │ │ ├── minion_tournament_medic.json
│ │ │ │ │ ├── minion_twilight_guardian.json
│ │ │ │ │ └── token_war_kodo.json
│ │ │ │ ├── paladin/
│ │ │ │ │ ├── hero_power_the_silver_hand.json
│ │ │ │ │ ├── minion_eadric_the_pure.json
│ │ │ │ │ ├── minion_murloc_knight.json
│ │ │ │ │ ├── minion_mysterious_challenger.json
│ │ │ │ │ ├── minion_tuskarr_jouster.json
│ │ │ │ │ ├── minion_warhorse_trainer.json
│ │ │ │ │ ├── secret_competitive_spirit.json
│ │ │ │ │ ├── spell_enter_the_coliseum.json
│ │ │ │ │ ├── spell_seal_of_champions.json
│ │ │ │ │ └── weapon_argent_lance.json
│ │ │ │ ├── priest/
│ │ │ │ │ ├── hero_power_heal.json
│ │ │ │ │ ├── minion_confessor_paletress.json
│ │ │ │ │ ├── minion_holy_champion.json
│ │ │ │ │ ├── minion_shadowfiend.json
│ │ │ │ │ ├── minion_spawn_of_shadows.json
│ │ │ │ │ ├── minion_wyrmrest_agent.json
│ │ │ │ │ ├── spell_confuse.json
│ │ │ │ │ ├── spell_convert.json
│ │ │ │ │ ├── spell_flash_heal.json
│ │ │ │ │ └── spell_power_word_glory.json
│ │ │ │ ├── rogue/
│ │ │ │ │ ├── hero_power_poisoned_dagger.json
│ │ │ │ │ ├── minion_anubarak.json
│ │ │ │ │ ├── minion_buccaneer.json
│ │ │ │ │ ├── minion_cutpurse.json
│ │ │ │ │ ├── minion_shado-pan_rider.json
│ │ │ │ │ ├── minion_shady_dealer.json
│ │ │ │ │ ├── minion_undercity_valiant.json
│ │ │ │ │ ├── spell_ambush.json
│ │ │ │ │ ├── spell_beneath_the_ground.json
│ │ │ │ │ ├── spell_burgle.json
│ │ │ │ │ ├── weapon_poisoned_blade.json
│ │ │ │ │ └── weapon_poisoned_dagger.json
│ │ │ │ ├── shaman/
│ │ │ │ │ ├── hero_power_lightning_jolt.json
│ │ │ │ │ ├── hero_power_totemic_slam.json
│ │ │ │ │ ├── minion_draenei_totemcarver.json
│ │ │ │ │ ├── minion_the_mistcaller.json
│ │ │ │ │ ├── minion_thunder_bluff_valiant.json
│ │ │ │ │ ├── minion_totem_golem.json
│ │ │ │ │ ├── minion_tuskarr_totemic.json
│ │ │ │ │ ├── spell_ancestral_knowledge.json
│ │ │ │ │ ├── spell_elemental_destruction.json
│ │ │ │ │ ├── spell_healing_wave.json
│ │ │ │ │ ├── spell_summon_healing_totem.json
│ │ │ │ │ ├── spell_summon_searing_totem.json
│ │ │ │ │ ├── spell_summon_stoneclaw_totem.json
│ │ │ │ │ ├── spell_summon_wrath_of_air_totem.json
│ │ │ │ │ └── weapon_charged_hammer.json
│ │ │ │ ├── warlock/
│ │ │ │ │ ├── hero_power_soul_tap.json
│ │ │ │ │ ├── minion_dreadsteed.json
│ │ │ │ │ ├── minion_fearsome_doomguard.json
│ │ │ │ │ ├── minion_tiny_knight_of_evil.json
│ │ │ │ │ ├── minion_void_crusher.json
│ │ │ │ │ ├── minion_wilfred_fizzlebang.json
│ │ │ │ │ ├── minion_wrathguard.json
│ │ │ │ │ ├── spell_dark_bargain.json
│ │ │ │ │ ├── spell_demonfuse.json
│ │ │ │ │ └── spell_fist_of_jaraxxus.json
│ │ │ │ └── warrior/
│ │ │ │ ├── hero_power_tank_up.json
│ │ │ │ ├── minion_alexstraszas_champion.json
│ │ │ │ ├── minion_magnataur_alpha.json
│ │ │ │ ├── minion_orgrimmar_aspirant.json
│ │ │ │ ├── minion_sea_reaver.json
│ │ │ │ ├── minion_sparring_partner.json
│ │ │ │ ├── minion_varian_wrynn.json
│ │ │ │ ├── spell_bash.json
│ │ │ │ ├── spell_bolster.json
│ │ │ │ └── weapon_kings_defender.json
│ │ │ └── the_old_gods/
│ │ │ ├── druid/
│ │ │ │ ├── minion_addled_grizzly.json
│ │ │ │ ├── minion_dark_arakkoa.json
│ │ │ │ ├── minion_fandral_staghelm.json
│ │ │ │ ├── minion_forbidden_ancient.json
│ │ │ │ ├── minion_klaxxi_amber-weaver.json
│ │ │ │ ├── minion_mire_keeper.json
│ │ │ │ ├── spell_feral_rage.json
│ │ │ │ ├── spell_feral_rage_1.json
│ │ │ │ ├── spell_feral_rage_2.json
│ │ │ │ ├── spell_feral_rage_3.json
│ │ │ │ ├── spell_mark_of_yshaarj.json
│ │ │ │ ├── spell_wisps_of_the_old_gods.json
│ │ │ │ ├── spell_wisps_of_the_old_gods_1.json
│ │ │ │ ├── spell_wisps_of_the_old_gods_2.json
│ │ │ │ └── spell_wisps_of_the_old_gods_3.json
│ │ │ ├── hunter/
│ │ │ │ ├── minion_carrion_grub.json
│ │ │ │ ├── minion_fiery_bat.json
│ │ │ │ ├── minion_forlorn_stalker.json
│ │ │ │ ├── minion_giant_sand_worm.json
│ │ │ │ ├── minion_infested_wolf.json
│ │ │ │ ├── minion_princess_huhuran.json
│ │ │ │ ├── spell_call_of_the_wild.json
│ │ │ │ ├── spell_infest.json
│ │ │ │ ├── spell_on_the_hunt.json
│ │ │ │ ├── token_mastiff.json
│ │ │ │ └── token_spider.json
│ │ │ ├── mage/
│ │ │ │ ├── minion_anomalus.json
│ │ │ │ ├── minion_cult_sorcerer.json
│ │ │ │ ├── minion_demented_frostcaller.json
│ │ │ │ ├── minion_faceless_summoner.json
│ │ │ │ ├── minion_servant_of_yogg_saron.json
│ │ │ │ ├── minion_twilight_flamecaller.json
│ │ │ │ ├── spell_cabalists_tome.json
│ │ │ │ ├── spell_forbidden_flame.json
│ │ │ │ └── spell_shatter.json
│ │ │ ├── neutral/
│ │ │ │ ├── minion_aberrant_berserker.json
│ │ │ │ ├── minion_amgam_rager.json
│ │ │ │ ├── minion_ancient_harbinger.json
│ │ │ │ ├── minion_beckoner_of_evil.json
│ │ │ │ ├── minion_bilefin_tidehunter.json
│ │ │ │ ├── minion_blackwater_pirate.json
│ │ │ │ ├── minion_blood_of_the_ancient_one.json
│ │ │ │ ├── minion_bog_creeper.json
│ │ │ │ ├── minion_corrupted_healbot.json
│ │ │ │ ├── minion_corrupted_seer.json
│ │ │ │ ├── minion_crazed_worshipper.json
│ │ │ │ ├── minion_cthun.json
│ │ │ │ ├── minion_cthuns_chosen.json
│ │ │ │ ├── minion_cult_apothecary.json
│ │ │ │ ├── minion_cyclopian_horror.json
│ │ │ │ ├── minion_darkspeaker.json
│ │ │ │ ├── minion_deathwing_dragonlord.json
│ │ │ │ ├── minion_disciple_of_cthun.json
│ │ │ │ ├── minion_doomcaller.json
│ │ │ │ ├── minion_duskboar.json
│ │ │ │ ├── minion_eater_of_secrets.json
│ │ │ │ ├── minion_eldritch_horror.json
│ │ │ │ ├── minion_evolved_kobold.json
│ │ │ │ ├── minion_faceless_behemoth.json
│ │ │ │ ├── minion_faceless_shambler.json
│ │ │ │ ├── minion_grotesque_dragonhawk.json
│ │ │ │ ├── minion_hogger_doom_of_elwynn.json
│ │ │ │ ├── minion_infested_tauren.json
│ │ │ │ ├── minion_midnight_drake.json
│ │ │ │ ├── minion_mukla_tyrant_of_the_vale.json
│ │ │ │ ├── minion_nat_the_darkfisher.json
│ │ │ │ ├── minion_nerubian_prophet.json
│ │ │ │ ├── minion_nzoth_the_corruptor.json
│ │ │ │ ├── minion_polluted_hoarder.json
│ │ │ │ ├── minion_psych-o-tron.json
│ │ │ │ ├── minion_scaled_nightmare.json
│ │ │ │ ├── minion_shifter_zerus.json
│ │ │ │ ├── minion_silithid_swarmer.json
│ │ │ │ ├── minion_skeram_cultist.json
│ │ │ │ ├── minion_soggoth_the_slitherer.json
│ │ │ │ ├── minion_spawn_of_nzoth.json
│ │ │ │ ├── minion_squirming_tentacle.json
│ │ │ │ ├── minion_tentacle_of_nzoth.json
│ │ │ │ ├── minion_the_boogeymonster.json
│ │ │ │ ├── minion_twilight_elder.json
│ │ │ │ ├── minion_twilight_geomancer.json
│ │ │ │ ├── minion_twilight_summoner.json
│ │ │ │ ├── minion_twin_emperor_veklor.json
│ │ │ │ ├── minion_twisted_worgen.json
│ │ │ │ ├── minion_validated_doomsayer.json
│ │ │ │ ├── minion_yogg_saron_hopes_end.json
│ │ │ │ ├── minion_yshaarj_rage_unbound.json
│ │ │ │ ├── minion_zealous_initiate.json
│ │ │ │ ├── token_faceless_destroyer.json
│ │ │ │ ├── token_ooze.json
│ │ │ │ ├── token_tauren_slime.json
│ │ │ │ ├── token_the_ancient_one.json
│ │ │ │ └── token_twin_emperor_veknilash.json
│ │ │ ├── paladin/
│ │ │ │ ├── hero_power_the_tidal_hand.json
│ │ │ │ ├── minion_ragnaros_lightlord.json
│ │ │ │ ├── minion_selfless_hero.json
│ │ │ │ ├── minion_steward_of_darkshire.json
│ │ │ │ ├── minion_vilefin_inquisitor.json
│ │ │ │ ├── spell_a_light_in_the_darkness.json
│ │ │ │ ├── spell_divine_strength.json
│ │ │ │ ├── spell_forbidden_healing.json
│ │ │ │ ├── spell_stand_against_darkness.json
│ │ │ │ ├── token_silver_hand_murloc.json
│ │ │ │ └── weapon_rallying_blade.json
│ │ │ ├── priest/
│ │ │ │ ├── minion_darkshire_alchemist.json
│ │ │ │ ├── minion_herald_volazj.json
│ │ │ │ ├── minion_hooded_acolyte.json
│ │ │ │ ├── minion_shifting_shade.json
│ │ │ │ ├── minion_twilight_darkmender.json
│ │ │ │ ├── spell_embrace_the_shadow.json
│ │ │ │ ├── spell_forbidden_shaping.json
│ │ │ │ ├── spell_power_word_tentacles.json
│ │ │ │ └── spell_shadow_word_horror.json
│ │ │ ├── rogue/
│ │ │ │ ├── minion_blade_of_cthun.json
│ │ │ │ ├── minion_bladed_cultist.json
│ │ │ │ ├── minion_shadowcaster.json
│ │ │ │ ├── minion_southsea_squidface.json
│ │ │ │ ├── minion_undercity_huckster.json
│ │ │ │ ├── minion_xaril_poisoned_mind.json
│ │ │ │ ├── spell_bloodthistle_toxin.json
│ │ │ │ ├── spell_briarthorn_toxin.json
│ │ │ │ ├── spell_fadeleaf_toxin.json
│ │ │ │ ├── spell_firebloom_toxin.json
│ │ │ │ ├── spell_journey_below.json
│ │ │ │ ├── spell_kingsblood_toxin.json
│ │ │ │ ├── spell_shadow_strike.json
│ │ │ │ └── spell_thistle_tea.json
│ │ │ ├── shaman/
│ │ │ │ ├── minion_eternal_sentinel.json
│ │ │ │ ├── minion_flamewreathed_faceless.json
│ │ │ │ ├── minion_hallazeal_the_ascended.json
│ │ │ │ ├── minion_master_of_evolution.json
│ │ │ │ ├── minion_thing_from_below.json
│ │ │ │ ├── spell_evolve.json
│ │ │ │ ├── spell_primal_fusion.json
│ │ │ │ ├── spell_stormcrack.json
│ │ │ │ ├── token_twilight_elemental.json
│ │ │ │ └── weapon_hammer_of_twilight.json
│ │ │ ├── warlock/
│ │ │ │ ├── minion_chogall.json
│ │ │ │ ├── minion_darkshire_councilman.json
│ │ │ │ ├── minion_darkshire_librarian.json
│ │ │ │ ├── minion_possessed_villager.json
│ │ │ │ ├── minion_usher_of_souls.json
│ │ │ │ ├── spell_doom.json
│ │ │ │ ├── spell_forbidden_ritual.json
│ │ │ │ ├── spell_renounce_darkness.json
│ │ │ │ ├── spell_spreading_madness.json
│ │ │ │ ├── token_icky_tentacle.json
│ │ │ │ └── token_shadowbeast.json
│ │ │ └── warrior/
│ │ │ ├── minion_ancient_shieldbearer.json
│ │ │ ├── minion_bloodhoof_brave.json
│ │ │ ├── minion_bloodsail_cultist.json
│ │ │ ├── minion_malkorok.json
│ │ │ ├── minion_nzoths_first_mate.json
│ │ │ ├── minion_ravaging_ghoul.json
│ │ │ ├── spell_blood_to_ichor.json
│ │ │ ├── spell_blood_warriors.json
│ │ │ ├── weapon_rusty_hook.json
│ │ │ └── weapon_tentacles_for_arms.json
│ │ ├── decks/
│ │ │ ├── aggro_shaman.json
│ │ │ ├── aggrodin.json
│ │ │ ├── beastrattle_hunter.json
│ │ │ ├── burgle_rogue.json
│ │ │ ├── face_hunter.json
│ │ │ ├── freeze_mage.json
│ │ │ ├── jade_druid.json
│ │ │ ├── jade_miracle_druid.json
│ │ │ ├── jade_rogue.json
│ │ │ ├── midrange_shaman.json
│ │ │ ├── miracle_rogue.json
│ │ │ ├── pirate_warrior.json
│ │ │ ├── reno_mage.json
│ │ │ ├── reno_priest.json
│ │ │ ├── renolock.json
│ │ │ └── wild_pirate_warrior.json
│ │ ├── formats/
│ │ │ ├── all.json
│ │ │ ├── standard.json
│ │ │ └── wild.json
│ │ └── training/
│ │ ├── budeget_effective_gvg_rogue_tempo_mech_synergy.json
│ │ ├── gvg_face_hunter_season_9_legend_24_na.json
│ │ └── handlock_mechanization_____.json
│ └── test/
│ └── java/
│ └── net/
│ └── demilich/
│ └── metastone/
│ └── tests/
│ └── ValidateCards.java
├── documentation/
│ ├── attributes.txt
│ ├── card.txt
│ ├── conditions.txt
│ ├── filters.txt
│ ├── knowledge.txt
│ ├── known_issues.txt
│ ├── spells.txt
│ ├── triggers.txt
│ └── valueproviders.txt
├── game/
│ ├── build.gradle
│ ├── lib/
│ │ └── jsoup-1.10.2.jar
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── net/
│ │ └── demilich/
│ │ └── metastone/
│ │ └── game/
│ │ ├── Attribute.java
│ │ ├── Environment.java
│ │ ├── GameContext.java
│ │ ├── Player.java
│ │ ├── PlayerAttribute.java
│ │ ├── TurnState.java
│ │ ├── actions/
│ │ │ ├── ActionType.java
│ │ │ ├── BattlecryAction.java
│ │ │ ├── DiscoverAction.java
│ │ │ ├── EndTurnAction.java
│ │ │ ├── GameAction.java
│ │ │ ├── HeroPowerAction.java
│ │ │ ├── IActionSelectionListener.java
│ │ │ ├── IBattlecryCondition.java
│ │ │ ├── PhysicalAttackAction.java
│ │ │ ├── PlayCardAction.java
│ │ │ ├── PlayChooseOneCardAction.java
│ │ │ ├── PlayMinionCardAction.java
│ │ │ ├── PlayPermanentCardAction.java
│ │ │ ├── PlaySpellCardAction.java
│ │ │ └── PlayWeaponCardAction.java
│ │ ├── behaviour/
│ │ │ ├── Behaviour.java
│ │ │ ├── DoNothingBehaviour.java
│ │ │ ├── FlatMonteCarlo.java
│ │ │ ├── GreedyOptimizeMove.java
│ │ │ ├── GreedyOptimizeTurn.java
│ │ │ ├── IBehaviour.java
│ │ │ ├── NoAggressionBehaviour.java
│ │ │ ├── PlayRandomBehaviour.java
│ │ │ ├── TranspositionTable.java
│ │ │ ├── heuristic/
│ │ │ │ ├── IGameStateHeuristic.java
│ │ │ │ ├── WeightedFeature.java
│ │ │ │ └── WeightedHeuristic.java
│ │ │ ├── human/
│ │ │ │ ├── ActionGroup.java
│ │ │ │ ├── HumanActionOptions.java
│ │ │ │ ├── HumanBehaviour.java
│ │ │ │ ├── HumanMulliganOptions.java
│ │ │ │ └── HumanTargetOptions.java
│ │ │ ├── learning/
│ │ │ │ ├── Brain.java
│ │ │ │ ├── IBrain.java
│ │ │ │ └── LearningBehaviour.java
│ │ │ ├── mcts/
│ │ │ │ ├── ITreePolicy.java
│ │ │ │ ├── MonteCarloTreeSearch.java
│ │ │ │ ├── Node.java
│ │ │ │ └── UctPolicy.java
│ │ │ ├── neutralnetwork/
│ │ │ │ ├── HiddenUnit.java
│ │ │ │ ├── InputUnit.java
│ │ │ │ ├── NeuralNetwork.java
│ │ │ │ └── Unit.java
│ │ │ └── threat/
│ │ │ ├── GameStateValueBehaviour.java
│ │ │ ├── ThreatBasedHeuristic.java
│ │ │ ├── ThreatLevel.java
│ │ │ └── cuckoo/
│ │ │ ├── CuckooAgent.java
│ │ │ ├── CuckooLearner.java
│ │ │ ├── IFitnessFunction.java
│ │ │ └── WinRateFitness.java
│ │ ├── cards/
│ │ │ ├── Card.java
│ │ │ ├── CardCatalogue.java
│ │ │ ├── CardCollection.java
│ │ │ ├── CardDescType.java
│ │ │ ├── CardParseException.java
│ │ │ ├── CardParser.java
│ │ │ ├── CardSet.java
│ │ │ ├── CardType.java
│ │ │ ├── ChooseBattlecryCard.java
│ │ │ ├── ChooseOneCard.java
│ │ │ ├── HeroCard.java
│ │ │ ├── IChooseOneCard.java
│ │ │ ├── MinionCard.java
│ │ │ ├── PermanentCard.java
│ │ │ ├── QuestCard.java
│ │ │ ├── Rarity.java
│ │ │ ├── SecretCard.java
│ │ │ ├── SpellCard.java
│ │ │ ├── SummonCard.java
│ │ │ ├── WeaponCard.java
│ │ │ ├── costmodifier/
│ │ │ │ ├── CardCostModifier.java
│ │ │ │ ├── OneTurnCostModifier.java
│ │ │ │ └── ToggleCostModifier.java
│ │ │ └── desc/
│ │ │ ├── ActorCardDesc.java
│ │ │ ├── AttributeDeserializer.java
│ │ │ ├── AuraDeserializer.java
│ │ │ ├── CardCostModifierDeserializer.java
│ │ │ ├── CardDesc.java
│ │ │ ├── ChooseBattlecryCardDesc.java
│ │ │ ├── ChooseOneCardDesc.java
│ │ │ ├── ConditionDeserializer.java
│ │ │ ├── Desc.java
│ │ │ ├── FilterDeserializer.java
│ │ │ ├── HeroCardDesc.java
│ │ │ ├── HeroPowerCardDesc.java
│ │ │ ├── MinionCardDesc.java
│ │ │ ├── ParseUtils.java
│ │ │ ├── ParseValueType.java
│ │ │ ├── PermanentCardDesc.java
│ │ │ ├── QuestCardDesc.java
│ │ │ ├── SecretCardDesc.java
│ │ │ ├── SourceDeserializer.java
│ │ │ ├── SpellCardDesc.java
│ │ │ ├── SpellDeserializer.java
│ │ │ ├── SummonCardDesc.java
│ │ │ ├── ValueProviderDeserializer.java
│ │ │ └── WeaponCardDesc.java
│ │ ├── decks/
│ │ │ ├── Deck.java
│ │ │ ├── DeckFactory.java
│ │ │ ├── DeckFormat.java
│ │ │ ├── MetaDeck.java
│ │ │ ├── RandomDeck.java
│ │ │ └── validation/
│ │ │ ├── ArbitraryDeckValidator.java
│ │ │ ├── DefaultDeckValidator.java
│ │ │ └── IDeckValidator.java
│ │ ├── entities/
│ │ │ ├── Actor.java
│ │ │ ├── Entity.java
│ │ │ ├── EntityType.java
│ │ │ ├── heroes/
│ │ │ │ ├── Hero.java
│ │ │ │ ├── HeroClass.java
│ │ │ │ └── MetaHero.java
│ │ │ ├── minions/
│ │ │ │ ├── Minion.java
│ │ │ │ ├── Permanent.java
│ │ │ │ ├── Race.java
│ │ │ │ ├── RelativeToSource.java
│ │ │ │ └── Summon.java
│ │ │ └── weapons/
│ │ │ └── Weapon.java
│ │ ├── events/
│ │ │ ├── AfterPhysicalAttackEvent.java
│ │ │ ├── AfterSpellCastedEvent.java
│ │ │ ├── AfterSummonEvent.java
│ │ │ ├── ArmorGainedEvent.java
│ │ │ ├── BeforeSummonEvent.java
│ │ │ ├── BoardChangedEvent.java
│ │ │ ├── CardPlayedEvent.java
│ │ │ ├── CardRevealedEvent.java
│ │ │ ├── DamageEvent.java
│ │ │ ├── DiscardEvent.java
│ │ │ ├── DrawCardEvent.java
│ │ │ ├── EnrageChangedEvent.java
│ │ │ ├── GameEvent.java
│ │ │ ├── GameEventType.java
│ │ │ ├── GameStartEvent.java
│ │ │ ├── HealEvent.java
│ │ │ ├── HeroPowerUsedEvent.java
│ │ │ ├── JoustEvent.java
│ │ │ ├── KillEvent.java
│ │ │ ├── OverloadEvent.java
│ │ │ ├── PhysicalAttackEvent.java
│ │ │ ├── PreDamageEvent.java
│ │ │ ├── QuestPlayedEvent.java
│ │ │ ├── QuestSuccessfulEvent.java
│ │ │ ├── SecretPlayedEvent.java
│ │ │ ├── SecretRevealedEvent.java
│ │ │ ├── SilenceEvent.java
│ │ │ ├── SpellCastedEvent.java
│ │ │ ├── SummonEvent.java
│ │ │ ├── TargetAcquisitionEvent.java
│ │ │ ├── TurnEndEvent.java
│ │ │ ├── TurnStartEvent.java
│ │ │ ├── WeaponDestroyedEvent.java
│ │ │ └── WeaponEquippedEvent.java
│ │ ├── gameconfig/
│ │ │ ├── GameConfig.java
│ │ │ └── PlayerConfig.java
│ │ ├── heroes/
│ │ │ └── powers/
│ │ │ ├── HeroPower.java
│ │ │ └── HeroPowerChooseOne.java
│ │ ├── logic/
│ │ │ ├── ActionLogic.java
│ │ │ ├── CustomCloneable.java
│ │ │ ├── GameLogic.java
│ │ │ ├── MatchResult.java
│ │ │ └── TargetLogic.java
│ │ ├── spells/
│ │ │ ├── AddAttributeSpell.java
│ │ │ ├── AddDeathrattleSpell.java
│ │ │ ├── AddQuestSpell.java
│ │ │ ├── AddSecretSpell.java
│ │ │ ├── AddSpellTriggerSpell.java
│ │ │ ├── AdjacentEffectSpell.java
│ │ │ ├── AuraBuffSpell.java
│ │ │ ├── BuffHeroSpell.java
│ │ │ ├── BuffSpell.java
│ │ │ ├── BuffWeaponSpell.java
│ │ │ ├── CardCostModifierSpell.java
│ │ │ ├── CastRandomSpellSpell.java
│ │ │ ├── CastRepeatedlySpell.java
│ │ │ ├── ChangeHeroPowerSpell.java
│ │ │ ├── ChangeHeroSpell.java
│ │ │ ├── ClearOverloadSpell.java
│ │ │ ├── CloneMinionSpell.java
│ │ │ ├── ComboSpell.java
│ │ │ ├── ConditionalAttackBonusSpell.java
│ │ │ ├── ConditionalEffectSpell.java
│ │ │ ├── ConditionalSpell.java
│ │ │ ├── CopyCardSpell.java
│ │ │ ├── CopyDeathrattleSpell.java
│ │ │ ├── CopyHeroPower.java
│ │ │ ├── CreateCardSpell.java
│ │ │ ├── CreateSummonSpell.java
│ │ │ ├── DamageSpell.java
│ │ │ ├── DestroyAllExceptOneSpell.java
│ │ │ ├── DestroySecretsSpell.java
│ │ │ ├── DestroySpell.java
│ │ │ ├── DiscardCardsFromDeckSpell.java
│ │ │ ├── DiscardSpell.java
│ │ │ ├── DiscoverCardSpell.java
│ │ │ ├── DiscoverDrawSpell.java
│ │ │ ├── DiscoverFilteredCardSpell.java
│ │ │ ├── DiscoverOptionSpell.java
│ │ │ ├── DiscoverRandomCardSpell.java
│ │ │ ├── DoubleAttackSpell.java
│ │ │ ├── DrawCardAndDoSomethingSpell.java
│ │ │ ├── DrawCardSpell.java
│ │ │ ├── DrawCardUntilConditionSpell.java
│ │ │ ├── EitherOrSpell.java
│ │ │ ├── EnrageSpell.java
│ │ │ ├── EquipRandomWeaponSpell.java
│ │ │ ├── EquipWeaponSpell.java
│ │ │ ├── ForceDeathPhaseSpell.java
│ │ │ ├── FromDeckToHandSpell.java
│ │ │ ├── FumbleSpell.java
│ │ │ ├── GainManaSpell.java
│ │ │ ├── HealSpell.java
│ │ │ ├── ICardPostProcessor.java
│ │ │ ├── ICardProvider.java
│ │ │ ├── JoustSpell.java
│ │ │ ├── MetaSpell.java
│ │ │ ├── MindControlSpell.java
│ │ │ ├── MisdirectSpell.java
│ │ │ ├── MissilesSpell.java
│ │ │ ├── ModifyAttributeSpell.java
│ │ │ ├── ModifyDamageSpell.java
│ │ │ ├── ModifyDurabilitySpell.java
│ │ │ ├── ModifyMaxManaSpell.java
│ │ │ ├── MultiTargetSpell.java
│ │ │ ├── NullSpell.java
│ │ │ ├── OverrideTargetSpell.java
│ │ │ ├── PutCopyInHandSpell.java
│ │ │ ├── PutMinionOnBoardFromDeckSpell.java
│ │ │ ├── PutMinionOnBoardSpell.java
│ │ │ ├── PutRandomMinionOnBoardSpell.java
│ │ │ ├── PutRandomSecretIntoPlaySpell.java
│ │ │ ├── RandomAttackTargetSpell.java
│ │ │ ├── RandomSpellTargetSpell.java
│ │ │ ├── RandomlyCastSpell.java
│ │ │ ├── RecastSpell.java
│ │ │ ├── ReceiveCardAndDoSomethingSpell.java
│ │ │ ├── ReceiveCardSpell.java
│ │ │ ├── ReceiveRandomCardSpell.java
│ │ │ ├── RefreshHeroPowerSpell.java
│ │ │ ├── RemoveAttributeSpell.java
│ │ │ ├── RemoveCardSpell.java
│ │ │ ├── RenounceClassSpell.java
│ │ │ ├── ReplaceCardLocationSpell.java
│ │ │ ├── ResurrectFromBothSpell.java
│ │ │ ├── ResurrectSpell.java
│ │ │ ├── ReturnMinionToHandSpell.java
│ │ │ ├── RevertableSpell.java
│ │ │ ├── ReviveMinionSpell.java
│ │ │ ├── SetAttackSpell.java
│ │ │ ├── SetHeroHpSpell.java
│ │ │ ├── SetHpSpell.java
│ │ │ ├── ShuffleMinionToDeckSpell.java
│ │ │ ├── ShuffleToDeckSpell.java
│ │ │ ├── SilenceSpell.java
│ │ │ ├── Spell.java
│ │ │ ├── SpellUtils.java
│ │ │ ├── StealRandomSecretSpell.java
│ │ │ ├── SummonCopySpell.java
│ │ │ ├── SummonNewAttackTargetSpell.java
│ │ │ ├── SummonOneOneCopySpell.java
│ │ │ ├── SummonRandomMinionFilteredSpell.java
│ │ │ ├── SummonRandomNotOnBoardSpell.java
│ │ │ ├── SummonRandomSpell.java
│ │ │ ├── SummonSpell.java
│ │ │ ├── SwapAttackAndHpSpell.java
│ │ │ ├── SwapAttackSpell.java
│ │ │ ├── SwapHpSpell.java
│ │ │ ├── SwipeSpell.java
│ │ │ ├── TargetPlayer.java
│ │ │ ├── TemporaryAttackSpell.java
│ │ │ ├── TransformCardSpell.java
│ │ │ ├── TransformMinionSpell.java
│ │ │ ├── TransformToRandomMinionSpell.java
│ │ │ ├── TriggerDeathrattleSpell.java
│ │ │ ├── aura/
│ │ │ │ ├── AttributeAura.java
│ │ │ │ ├── Aura.java
│ │ │ │ ├── BuffAura.java
│ │ │ │ └── EnrageAura.java
│ │ │ ├── custom/
│ │ │ │ ├── AlarmOBotSpell.java
│ │ │ │ ├── BetrayalSpell.java
│ │ │ │ ├── FacelessSpell.java
│ │ │ │ ├── HeraldVolajzSpell.java
│ │ │ │ ├── HolyWrathSpell.java
│ │ │ │ ├── KelThuzadSpell.java
│ │ │ │ ├── MadamGoyaSpell.java
│ │ │ │ ├── MergeSpell.java
│ │ │ │ ├── MoatLurkerSpell.java
│ │ │ │ ├── PoisonSeedsSpell.java
│ │ │ │ ├── PutMiniCopyInHandSpell.java
│ │ │ │ ├── ShadowMadnessSpell.java
│ │ │ │ └── ShifterZerusSpell.java
│ │ │ ├── desc/
│ │ │ │ ├── BattlecryDesc.java
│ │ │ │ ├── ISpellConditionChecker.java
│ │ │ │ ├── SpellArg.java
│ │ │ │ ├── SpellDesc.java
│ │ │ │ ├── SpellFactory.java
│ │ │ │ ├── aura/
│ │ │ │ │ ├── AuraArg.java
│ │ │ │ │ └── AuraDesc.java
│ │ │ │ ├── condition/
│ │ │ │ │ ├── AndCondition.java
│ │ │ │ │ ├── AttributeCondition.java
│ │ │ │ │ ├── CardCountCondition.java
│ │ │ │ │ ├── CardPropertyCondition.java
│ │ │ │ │ ├── ComboCondition.java
│ │ │ │ │ ├── ComparisonCondition.java
│ │ │ │ │ ├── Condition.java
│ │ │ │ │ ├── ConditionArg.java
│ │ │ │ │ ├── ConditionDesc.java
│ │ │ │ │ ├── ControlsSecretCondition.java
│ │ │ │ │ ├── DeckContainsCondition.java
│ │ │ │ │ ├── GraveyardContainsCondition.java
│ │ │ │ │ ├── GraveyardCountCondition.java
│ │ │ │ │ ├── HasAttackedCondition.java
│ │ │ │ │ ├── HasEntitiesOnBoardCondition.java
│ │ │ │ │ ├── HasEntityCondition.java
│ │ │ │ │ ├── HasHeroPowerCondition.java
│ │ │ │ │ ├── HasWeaponCondition.java
│ │ │ │ │ ├── HighlanderDeckCondition.java
│ │ │ │ │ ├── HoldsCardCondition.java
│ │ │ │ │ ├── IsDamagedCondition.java
│ │ │ │ │ ├── IsDeadCondition.java
│ │ │ │ │ ├── ManaCostCondition.java
│ │ │ │ │ ├── ManaMaxedCondition.java
│ │ │ │ │ ├── MinionCountCondition.java
│ │ │ │ │ ├── MinionOnBoardCondition.java
│ │ │ │ │ ├── OrCondition.java
│ │ │ │ │ ├── OwnedByPlayerCondition.java
│ │ │ │ │ ├── RaceCondition.java
│ │ │ │ │ └── RandomCondition.java
│ │ │ │ ├── filter/
│ │ │ │ │ ├── AndFilter.java
│ │ │ │ │ ├── AttributeFilter.java
│ │ │ │ │ ├── CardFilter.java
│ │ │ │ │ ├── DamagedFilter.java
│ │ │ │ │ ├── EntityFilter.java
│ │ │ │ │ ├── FilterArg.java
│ │ │ │ │ ├── FilterDesc.java
│ │ │ │ │ ├── HighestAttributeFilter.java
│ │ │ │ │ ├── InDeckFilter.java
│ │ │ │ │ ├── InHandFilter.java
│ │ │ │ │ ├── Operation.java
│ │ │ │ │ ├── OrFilter.java
│ │ │ │ │ ├── RaceFilter.java
│ │ │ │ │ └── SpecificCardFilter.java
│ │ │ │ ├── manamodifier/
│ │ │ │ │ ├── CardCostModifierArg.java
│ │ │ │ │ └── CardCostModifierDesc.java
│ │ │ │ ├── source/
│ │ │ │ │ ├── CardSource.java
│ │ │ │ │ ├── DeckSource.java
│ │ │ │ │ ├── DefaultSource.java
│ │ │ │ │ ├── HandSource.java
│ │ │ │ │ ├── SourceArg.java
│ │ │ │ │ └── SourceDesc.java
│ │ │ │ ├── trigger/
│ │ │ │ │ ├── EventTriggerArg.java
│ │ │ │ │ ├── EventTriggerDesc.java
│ │ │ │ │ ├── EventTriggerDeserializer.java
│ │ │ │ │ └── TriggerDesc.java
│ │ │ │ └── valueprovider/
│ │ │ │ ├── AlgebraicOperation.java
│ │ │ │ ├── AlgebraicValueProvider.java
│ │ │ │ ├── AttributeCounter.java
│ │ │ │ ├── AttributeValueProvider.java
│ │ │ │ ├── CardCounter.java
│ │ │ │ ├── CardsPlayedValueProvider.java
│ │ │ │ ├── ConditionalValueProvider.java
│ │ │ │ ├── DeadMinionsThisTurn.java
│ │ │ │ ├── EntityCounter.java
│ │ │ │ ├── HighestAttributeValueProvider.java
│ │ │ │ ├── MinionSummonValueProvider.java
│ │ │ │ ├── PlayerAttributeValueProvider.java
│ │ │ │ ├── RandomValueProvider.java
│ │ │ │ ├── ValueProvider.java
│ │ │ │ ├── ValueProviderArg.java
│ │ │ │ └── ValueProviderDesc.java
│ │ │ └── trigger/
│ │ │ ├── AfterMinionPlayedTrigger.java
│ │ │ ├── AfterMinionSummonedTrigger.java
│ │ │ ├── AfterPhysicalAttackTrigger.java
│ │ │ ├── AfterSpellCastedTrigger.java
│ │ │ ├── ArmorGainedTrigger.java
│ │ │ ├── BeforeMinionPlayedTrigger.java
│ │ │ ├── BeforeMinionSummonedTrigger.java
│ │ │ ├── BoardChangedTrigger.java
│ │ │ ├── CardDrawnTrigger.java
│ │ │ ├── CardPlayedTrigger.java
│ │ │ ├── CardReceivedTrigger.java
│ │ │ ├── DamageCausedTrigger.java
│ │ │ ├── DamageReceivedTrigger.java
│ │ │ ├── DiscardTrigger.java
│ │ │ ├── EnrageChangedTrigger.java
│ │ │ ├── FatalDamageTrigger.java
│ │ │ ├── GameEventTrigger.java
│ │ │ ├── GameStartTrigger.java
│ │ │ ├── GameStateChangedTrigger.java
│ │ │ ├── HealingTrigger.java
│ │ │ ├── IGameEventListener.java
│ │ │ ├── InspireTrigger.java
│ │ │ ├── MinionDeathTrigger.java
│ │ │ ├── MinionPlayedTrigger.java
│ │ │ ├── MinionSummonedTrigger.java
│ │ │ ├── OverloadTrigger.java
│ │ │ ├── PhysicalAttackTrigger.java
│ │ │ ├── PreDamageTrigger.java
│ │ │ ├── QuestPlayedTrigger.java
│ │ │ ├── QuestSuccessTrigger.java
│ │ │ ├── SecretPlayedTrigger.java
│ │ │ ├── SecretRevealedTrigger.java
│ │ │ ├── SilenceTrigger.java
│ │ │ ├── SpellCastedTrigger.java
│ │ │ ├── SpellTrigger.java
│ │ │ ├── TargetAcquisitionTrigger.java
│ │ │ ├── TriggerManager.java
│ │ │ ├── TurnEndTrigger.java
│ │ │ ├── TurnStartTrigger.java
│ │ │ ├── WeaponDestroyedTrigger.java
│ │ │ ├── WeaponEquippedTrigger.java
│ │ │ └── types/
│ │ │ ├── Quest.java
│ │ │ └── Secret.java
│ │ ├── statistics/
│ │ │ ├── GameStatistics.java
│ │ │ └── Statistic.java
│ │ ├── targeting/
│ │ │ ├── CardLocation.java
│ │ │ ├── CardReference.java
│ │ │ ├── EntityReference.java
│ │ │ ├── IdFactory.java
│ │ │ ├── TargetSelection.java
│ │ │ └── TargetType.java
│ │ └── utils/
│ │ ├── GameTagUtils.java
│ │ └── TagValueType.java
│ └── test/
│ └── java/
│ └── net/
│ └── demilich/
│ └── metastone/
│ └── tests/
│ ├── AdvancedMechanicTests.java
│ ├── AuraTests.java
│ ├── BasicTests.java
│ ├── BlackrockMountainTests.java
│ ├── CardInteractionTests.java
│ ├── CloningTest.java
│ ├── DebugContext.java
│ ├── HeroPowerTest.java
│ ├── ManaTests.java
│ ├── MassTest.java
│ ├── PoisonSeedsTests.java
│ ├── SecretTest.java
│ ├── SpecialCardTests.java
│ ├── TargetingTests.java
│ ├── TechnicalTests.java
│ ├── TestAction.java
│ ├── TestBase.java
│ ├── TestMinionCard.java
│ ├── TestSecretCard.java
│ ├── TestSpellCard.java
│ ├── TheOldGodsTests.java
│ ├── WeaponTests.java
│ └── allcards/
│ ├── ClassicMageCards.java
│ └── ClassicNeutralCards.java
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── shared/
├── build.gradle
├── lib/
│ └── nitty-gritty-mvc.jar
└── src/
└── main/
└── java/
└── net/
└── demilich/
└── metastone/
├── GameNotification.java
├── NotificationProxy.java
├── game/
│ └── behaviour/
│ └── threat/
│ ├── FeatureVector.java
│ └── WeightedFeature.java
├── trainingmode/
│ ├── ITrainingDataListener.java
│ ├── RequestTrainingDataNotification.java
│ └── TrainingData.java
└── utils/
├── ICallback.java
├── IDisposable.java
├── MathUtils.java
├── MetastoneProperties.java
├── ResourceInputStream.java
├── ResourceLoader.java
├── Tuple.java
├── UserHomeMetastone.java
└── VersionInfo.java
Showing preview only (301K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3255 symbols across 635 files)
FILE: app/src/main/java/net/demilich/metastone/ApplicationFacade.java
class ApplicationFacade (line 39) | public class ApplicationFacade extends Facade<GameNotification> {
method getInstance (line 41) | @SuppressWarnings("unchecked")
method ApplicationFacade (line 50) | public ApplicationFacade() {
method startUp (line 96) | public void startUp() {
FILE: app/src/main/java/net/demilich/metastone/ApplicationStartupCommand.java
class ApplicationStartupCommand (line 15) | public class ApplicationStartupCommand extends SimpleCommand<GameNotific...
method execute (line 17) | @Override
FILE: app/src/main/java/net/demilich/metastone/DevCardTools.java
class DevCardTools (line 31) | public class DevCardTools {
method assignUniqueIdToEachCard (line 33) | public static void assignUniqueIdToEachCard() {
method cardListFromImages (line 90) | public static void cardListFromImages(String path) throws IOException {
method changeFileNameToClassName (line 103) | private static String changeFileNameToClassName(String name) {
method compareClassesWithCardList (line 116) | public static void compareClassesWithCardList(String path) throws IOEx...
method containsExpression (line 145) | private static int containsExpression(List<String> lines, String expre...
method extractId (line 156) | private static int extractId(String line) {
method formatJsons (line 167) | public static void formatJsons() {
method getImplementedCardsAsLines (line 183) | private static List<String> getImplementedCardsAsLines() {
method prettyPrintFile (line 197) | private static void prettyPrintFile(File file) throws IOException {
method toCanonName (line 215) | private static String toCanonName(String name) {
method updateCardCatalogue (line 219) | public static void updateCardCatalogue() {
FILE: app/src/main/java/net/demilich/metastone/MetaStone.java
class MetaStone (line 19) | public class MetaStone extends Application {
method main (line 23) | public static void main(String[] args) {
method start (line 37) | @Override
FILE: app/src/main/java/net/demilich/metastone/PlayGameCommand.java
class PlayGameCommand (line 7) | public class PlayGameCommand extends SimpleCommand<GameNotification> {
method execute (line 9) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/DigitFactory.java
class DigitFactory (line 28) | public class DigitFactory {
method applyFontColor (line 40) | private static void applyFontColor(ImageView image, Color color) {
method getCachedDigitImage (line 50) | private static Node getCachedDigitImage(int number, Color color) {
method saveAllDigits (line 69) | public static void saveAllDigits() {
method showPreRenderedDigits (line 95) | public static void showPreRenderedDigits(Group group, int number) {
method showPreRenderedDigits (line 99) | public static void showPreRenderedDigits(Group group, int number, Colo...
FILE: app/src/main/java/net/demilich/metastone/gui/DigitTemplate.java
class DigitTemplate (line 10) | public class DigitTemplate extends HBox {
method DigitTemplate (line 15) | public DigitTemplate() {
FILE: app/src/main/java/net/demilich/metastone/gui/IconFactory.java
class IconFactory (line 10) | public class IconFactory {
method getClassIcon (line 15) | public static Image getClassIcon(HeroClass heroClass) {
method getDefaultCardBack (line 22) | public static Image getDefaultCardBack() {
method getDialogIcon (line 27) | public static Image getDialogIcon(DialogType dialogType) {
method getHeroIconUrl (line 49) | public static String getHeroIconUrl(HeroClass heroClass) {
method getHeroPowerIconUrl (line 88) | public static String getHeroPowerIconUrl(HeroPower heroPower) {
method getImageUrl (line 127) | public static String getImageUrl(String imageName) {
method getRarityColor (line 132) | public static Color getRarityColor(Rarity rarity) {
method getSummonHelper (line 158) | public static Image getSummonHelper() {
method getTargetIcon (line 163) | public static Image getTargetIcon() {
method IconFactory (line 168) | private IconFactory() {
FILE: app/src/main/java/net/demilich/metastone/gui/autoupdate/AutoUpdateMediator.java
class AutoUpdateMediator (line 25) | public class AutoUpdateMediator extends Mediator<GameNotification> {
method AutoUpdateMediator (line 31) | public AutoUpdateMediator() {
method handleNotification (line 35) | @Override
method listNotificationInterests (line 50) | @Override
method showUpdateNotification (line 58) | private void showUpdateNotification(VersionInfo versionInfo) {
method onNotificationClicked (line 74) | private void onNotificationClicked(ActionEvent event) {
FILE: app/src/main/java/net/demilich/metastone/gui/autoupdate/CheckForUpdateCommand.java
class CheckForUpdateCommand (line 21) | public class CheckForUpdateCommand extends SimpleCommand<GameNotificatio...
method execute (line 27) | @Override
method check (line 32) | private void check() {
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleBatchResult.java
class BattleBatchResult (line 8) | public class BattleBatchResult {
method BattleBatchResult (line 18) | public BattleBatchResult(Deck deck1, Deck deck2, int numberOfGames) {
method getDeck1 (line 24) | public Deck getDeck1() {
method getDeck1Winrate (line 28) | public double getDeck1Winrate() {
method getDeck2 (line 32) | public Deck getDeck2() {
method getDeck2Winrate (line 36) | public double getDeck2Winrate() {
method getNumberOfGames (line 40) | public int getNumberOfGames() {
method getPlayer1Results (line 44) | public GameStatistics getPlayer1Results() {
method getPlayer2Results (line 48) | public GameStatistics getPlayer2Results() {
method getProgress (line 52) | public double getProgress() {
method isCompleted (line 56) | public boolean isCompleted() {
method onGameEnded (line 60) | public void onGameEnded(GameContext result) {
method setCompleted (line 69) | public void setCompleted(boolean completed) {
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleBatchResultToken.java
class BattleBatchResultToken (line 16) | public class BattleBatchResultToken extends BorderPane {
method BattleBatchResultToken (line 40) | public BattleBatchResultToken() {
method displayBatchResult (line 57) | public void displayBatchResult(BattleBatchResult result) {
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleConfig.java
class BattleConfig (line 8) | public class BattleConfig {
method BattleConfig (line 14) | public BattleConfig(int numberOfGames, IBehaviour behaviour, Collectio...
method getBehaviour (line 20) | public IBehaviour getBehaviour() {
method getDecks (line 24) | public Collection<Deck> getDecks() {
method getNumberOfGames (line 28) | public int getNumberOfGames() {
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleDeckResult.java
class BattleDeckResult (line 12) | public class BattleDeckResult {
method BattleDeckResult (line 18) | public BattleDeckResult(String deckName, GameStatistics deckStatistics) {
method deckNameProperty (line 24) | public final StringProperty deckNameProperty() {
method deckStatisticsProperty (line 28) | public final ObjectProperty<GameStatistics> deckStatisticsProperty() {
method getDeckName (line 32) | public final String getDeckName() {
method getDeckStatistics (line 36) | public final GameStatistics getDeckStatistics() {
method getWinRate (line 40) | public final double getWinRate() {
method setDeckName (line 44) | public final void setDeckName(final String deckName) {
method setDeckStatistics (line 48) | public final void setDeckStatistics(final GameStatistics deckStatistic...
method setWinRate (line 52) | public final void setWinRate(final double winRate) {
method winRateProperty (line 56) | public final DoubleProperty winRateProperty() {
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksConfigView.java
class BattleOfDecksConfigView (line 29) | public class BattleOfDecksConfigView extends BorderPane {
method BattleOfDecksConfigView (line 50) | public BattleOfDecksConfigView() {
method handleAddButton (line 76) | private void handleAddButton(ActionEvent event) {
method handleRemoveButton (line 82) | private void handleRemoveButton(ActionEvent event) {
method handleStartButton (line 88) | private void handleStartButton(ActionEvent event) {
method injectDecks (line 96) | public void injectDecks(List<Deck> decks) {
method setupBehaviourBox (line 107) | private void setupBehaviourBox() {
method setupNumberOfGamesBox (line 113) | private void setupNumberOfGamesBox() {
method injectDeckFormats (line 123) | public void injectDeckFormats(List<DeckFormat> deckFormats) {
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksMediator.java
class BattleOfDecksMediator (line 13) | public class BattleOfDecksMediator extends Mediator<GameNotification> {
method BattleOfDecksMediator (line 20) | public BattleOfDecksMediator() {
method handleNotification (line 26) | @SuppressWarnings("unchecked")
method listNotificationInterests (line 48) | @Override
method onRegister (line 58) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksResultView.java
class BattleOfDecksResultView (line 24) | public class BattleOfDecksResultView extends BorderPane {
method BattleOfDecksResultView (line 37) | @SuppressWarnings("unchecked")
method updateResults (line 94) | @SuppressWarnings("unchecked")
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleResult.java
class BattleResult (line 11) | public class BattleResult {
method BattleResult (line 17) | public BattleResult(int numberOfGames) {
method addBatchResult (line 21) | public void addBatchResult(BattleBatchResult batchResult) {
method getBatchResults (line 27) | public List<BattleBatchResult> getBatchResults() {
method getDeckResults (line 33) | public List<BattleDeckResult> getDeckResults() {
method getNumberOfGames (line 44) | public int getNumberOfGames() {
method onGameEnded (line 48) | public void onGameEnded(GameContext result) {
method updateStats (line 54) | private void updateStats(Player player) {
FILE: app/src/main/java/net/demilich/metastone/gui/battleofdecks/StartBattleOfDecksCommand.java
class StartBattleOfDecksCommand (line 28) | public class StartBattleOfDecksCommand extends SimpleCommand<GameNotific...
class PlayGameTask (line 30) | private class PlayGameTask implements Callable<Void> {
method PlayGameTask (line 36) | public PlayGameTask(Deck deck1, Deck deck2, IBehaviour behaviour, Ba...
method call (line 44) | @Override
method execute (line 73) | @Override
method periodicUpdate (line 139) | private void periodicUpdate() {
FILE: app/src/main/java/net/demilich/metastone/gui/cards/CardProxy.java
class CardProxy (line 15) | public class CardProxy extends Proxy<GameNotification> {
method CardProxy (line 20) | public CardProxy() {
FILE: app/src/main/java/net/demilich/metastone/gui/cards/CardToken.java
class CardToken (line 23) | public class CardToken extends BorderPane {
method CardToken (line 49) | protected CardToken(String fxml) {
method getCard (line 63) | public Card getCard() {
method setCard (line 67) | public void setCard(Card card) {
method setCard (line 71) | public void setCard(GameContext context, Card card, Player player) {
method setNonCard (line 98) | public void setNonCard(String name, String description) {
method setRarity (line 109) | private void setRarity(Rarity rarity) {
method setScoreValue (line 115) | protected void setScoreValue(Group group, int value) {
method setScoreValue (line 119) | protected void setScoreValue(Group group, int value, int baseValue) {
method setScoreValue (line 127) | protected void setScoreValue(Group group, int value, int baseValue, in...
method setScoreValueLowerIsBetter (line 137) | private void setScoreValueLowerIsBetter(Group group, int value, int ba...
FILE: app/src/main/java/net/demilich/metastone/gui/cards/CardTokenFactory.java
class CardTokenFactory (line 10) | public class CardTokenFactory {
method CardTokenFactory (line 16) | public CardTokenFactory() {
method createHandCard (line 22) | public CardToken createHandCard(GameContext context, Card card, Player...
method getHandCard (line 28) | private HandCard getHandCard() {
FILE: app/src/main/java/net/demilich/metastone/gui/cards/CardTooltip.java
class CardTooltip (line 11) | public class CardTooltip extends CardToken {
method CardTooltip (line 16) | public CardTooltip() {
method setCard (line 20) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/cards/HandCard.java
class HandCard (line 16) | public class HandCard extends CardToken {
method HandCard (line 28) | public HandCard() {
method hideCard (line 33) | private void hideCard(boolean hide) {
method setCard (line 46) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/common/BehaviourStringConverter.java
class BehaviourStringConverter (line 6) | public class BehaviourStringConverter extends StringConverter<IBehaviour> {
method fromString (line 8) | @Override
method toString (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/common/CardSetStringConverter.java
class CardSetStringConverter (line 6) | public class CardSetStringConverter extends StringConverter<CardSet> {
method fromString (line 8) | @Override
method toString (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/common/ComboBoxKeyHandler.java
class ComboBoxKeyHandler (line 11) | public class ComboBoxKeyHandler<T> implements EventHandler<KeyEvent> {
method ComboBoxKeyHandler (line 19) | public ComboBoxKeyHandler(ComboBox<T> box) {
method handle (line 24) | @Override
method select (line 54) | private void select(int index) {
method select (line 58) | @SuppressWarnings("rawtypes")
FILE: app/src/main/java/net/demilich/metastone/gui/common/DeckFormatStringConverter.java
class DeckFormatStringConverter (line 6) | public class DeckFormatStringConverter extends StringConverter<DeckForma...
method fromString (line 8) | @Override
method toString (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/common/DeckStringConverter.java
class DeckStringConverter (line 6) | public class DeckStringConverter extends StringConverter<Deck> {
method fromString (line 8) | @Override
method toString (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/common/HeroStringConverter.java
class HeroStringConverter (line 6) | public class HeroStringConverter extends StringConverter<HeroCard> {
method fromString (line 8) | @Override
method toString (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/common/IntegerTextField.java
class IntegerTextField (line 6) | public class IntegerTextField extends RestrictedTextField {
method IntegerTextField (line 10) | public IntegerTextField(int maxLength) {
method getIntValue (line 15) | public int getIntValue() {
method setIntValue (line 19) | public void setIntValue(int value) {
method validInput (line 23) | @Override
method valueProperty (line 31) | public IntegerProperty valueProperty() {
FILE: app/src/main/java/net/demilich/metastone/gui/common/RestrictedTextField.java
class RestrictedTextField (line 16) | public class RestrictedTextField extends TextField {
method RestrictedTextField (line 22) | public RestrictedTextField() {
method getMaxLength (line 52) | public int getMaxLength() {
method getRestrict (line 56) | public String getRestrict() {
method maxLengthProperty (line 60) | public IntegerProperty maxLengthProperty() {
method restrictProperty (line 64) | public StringProperty restrictProperty() {
method setMaxLength (line 74) | public void setMaxLength(int maxLength) {
method setRestrict (line 86) | public void setRestrict(String restrict) {
method validInput (line 90) | protected void validInput(String validInput) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/AddCardToDeckCommand.java
class AddCardToDeckCommand (line 8) | public class AddCardToDeckCommand extends SimpleCommand<GameNotification> {
method execute (line 10) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardEntry.java
class CardEntry (line 12) | public class CardEntry extends HBox {
method CardEntry (line 27) | public CardEntry() {
method addCard (line 41) | public void addCard(Card card) {
method getCard (line 50) | public Card getCard() {
method resetStackCount (line 54) | public void resetStackCount() {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardEntryFactory.java
class CardEntryFactory (line 8) | public class CardEntryFactory {
method CardEntryFactory (line 14) | public CardEntryFactory() {
method createCardEntry (line 20) | public CardEntry createCardEntry(Card card) {
method getCardEntry (line 27) | private CardEntry getCardEntry() {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardFilter.java
class CardFilter (line 6) | public class CardFilter {
method CardFilter (line 12) | public CardFilter(String text, CardSet set, DeckFormat format) {
method getFormat (line 18) | public DeckFormat getFormat() {
method getSet (line 22) | public CardSet getSet() {
method getText (line 26) | public String getText() {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardFilterView.java
class CardFilterView (line 21) | public class CardFilterView extends HBox {
method CardFilterView (line 34) | public CardFilterView(List<DeckFormat> deckFormats) {
method filterChanged (line 61) | private void filterChanged() {
method formatChanged (line 70) | private void formatChanged(ObservableValue<? extends DeckFormat> obser...
method injectDeckFormats (line 87) | public void injectDeckFormats(List<DeckFormat> deckFormats) {
method setChanged (line 91) | private void setChanged(ObservableValue<? extends CardSet> observable,...
method textChanged (line 95) | private void textChanged(ObservableValue<? extends String> observable,...
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardListView.java
class CardListView (line 15) | public class CardListView extends VBox implements EventHandler<MouseEven...
method CardListView (line 20) | public CardListView() {
method clearChildren (line 26) | private void clearChildren() {
method displayDeck (line 33) | public void displayDeck(Deck deck) {
method handle (line 52) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardView.java
class CardView (line 20) | public class CardView extends BorderPane implements EventHandler<MouseEv...
method CardView (line 42) | public CardView() {
method changeOffset (line 61) | private void changeOffset(int delta) {
method displayCards (line 70) | public void displayCards(List<Card> cards) {
method displayCurrentPage (line 76) | private void displayCurrentPage() {
method handle (line 91) | @Override
method setupCardWidgets (line 98) | private void setupCardWidgets() {
method updatePageLabel (line 112) | private void updatePageLabel() {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/ChangeDeckNameCommand.java
class ChangeDeckNameCommand (line 7) | public class ChangeDeckNameCommand extends SimpleCommand<GameNotificatio...
method execute (line 9) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/ChooseClassView.java
class ChooseClassView (line 19) | public class ChooseClassView extends BorderPane implements EventHandler<...
method ChooseClassView (line 55) | public ChooseClassView() {
method handle (line 84) | @Override
method onArbitraryBoxChanged (line 111) | private void onArbitraryBoxChanged(ObservableValue<? extends Boolean> ...
method setupArbitraryBox (line 117) | private void setupArbitraryBox() {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckBuilderMediator.java
class DeckBuilderMediator (line 16) | public class DeckBuilderMediator extends Mediator<GameNotification> {
method DeckBuilderMediator (line 22) | public DeckBuilderMediator() {
method handleNotification (line 27) | @SuppressWarnings("unchecked")
method listNotificationInterests (line 66) | @Override
method onRegister (line 80) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckBuilderView.java
class DeckBuilderView (line 27) | public class DeckBuilderView extends BorderPane implements EventHandler<...
method DeckBuilderView (line 57) | public DeckBuilderView() {
method activeDeckChanged (line 82) | public void activeDeckChanged(Deck activeDeck) {
method createNewDeck (line 97) | public void createNewDeck() {
method displayDecks (line 102) | public void displayDecks(List<Deck> decks) {
method editDeck (line 107) | public void editDeck(Deck deck) {
method filteredCards (line 121) | public void filteredCards(List<Card> filteredCards) {
method handle (line 125) | @Override
method injectDeckFormats (line 134) | public void injectDeckFormats(List<DeckFormat> deckFormats) {
method showBottomBar (line 138) | private void showBottomBar(Node content) {
method showLowerInfoArea (line 143) | private void showLowerInfoArea(Node content) {
method showMainArea (line 148) | private void showMainArea(Node content) {
method showSidebar (line 152) | private void showSidebar(Node content) {
method showUpperInfoArea (line 157) | private void showUpperInfoArea(Node content) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckEntry.java
class DeckEntry (line 21) | public class DeckEntry extends HBox {
method DeckEntry (line 34) | public DeckEntry() {
method getDeck (line 48) | public Deck getDeck() {
method setDeck (line 52) | public void setDeck(Deck deck) {
method handleDeleteDeck (line 58) | private void handleDeleteDeck(ActionEvent event) {
method onDeleteDeckDialog (line 65) | private void onDeleteDeckDialog(DialogResult result) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckFormatProxy.java
class DeckFormatProxy (line 28) | public class DeckFormatProxy extends Proxy<GameNotification> {
method DeckFormatProxy (line 38) | public DeckFormatProxy() {
method getDeckFormatByName (line 42) | public DeckFormat getDeckFormatByName(String deckName) {
method getDeckFormats (line 51) | public List<DeckFormat> getDeckFormats() {
method loadDeckFormats (line 55) | public void loadDeckFormats() throws IOException, URISyntaxException {
method loadDeckFormats (line 65) | private void loadDeckFormats(Collection<ResourceInputStream> inputStre...
method parseStandardDeckFormat (line 86) | private DeckFormat parseStandardDeckFormat(Map<String, Object> map) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckInfoView.java
class DeckInfoView (line 24) | public class DeckInfoView extends HBox implements EventHandler<ActionEve...
method DeckInfoView (line 37) | public DeckInfoView() {
method handle (line 50) | @Override
method onDialogClosed (line 73) | @Override
method updateDeck (line 81) | public void updateDeck(Deck deck) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckListView.java
class DeckListView (line 17) | public class DeckListView extends VBox implements EventHandler<MouseEven...
method DeckListView (line 22) | public DeckListView() {
method clearChildren (line 37) | private void clearChildren() {
method displayDecks (line 44) | public void displayDecks(List<Deck> decks) {
method handle (line 55) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckNameView.java
class DeckNameView (line 17) | public class DeckNameView extends HBox implements ChangeListener<String> {
method DeckNameView (line 25) | public DeckNameView() {
method changed (line 39) | @Override
method updateDeck (line 44) | public void updateDeck(Deck deck) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckProxy.java
class DeckProxy (line 43) | public class DeckProxy extends Proxy<GameNotification> {
method DeckProxy (line 56) | public DeckProxy() {
method addCardToDeck (line 71) | public boolean addCardToDeck(Card card) {
method getActiveDeck (line 79) | public Deck getActiveDeck() {
method getCards (line 83) | public List<Card> getCards(HeroClass heroClass) {
method getDeckByName (line 101) | public Deck getDeckByName(String deckName) {
method getDecks (line 110) | public List<Deck> getDecks() {
method deleteDeck (line 114) | public void deleteDeck(Deck deck) {
method loadDecks (line 133) | public void loadDecks() throws IOException, URISyntaxException {
method copyDecksFromResources (line 142) | private void copyDecksFromResources() throws IOException, URISyntaxExc...
method loadMetaDecks (line 153) | private void loadMetaDecks(Collection<ResourceInputStream> inputStream...
method loadStandardDecks (line 175) | private void loadStandardDecks(Collection<ResourceInputStream> inputSt...
method nameAvailable (line 201) | public boolean nameAvailable(Deck deck) {
method parseMetaDeck (line 210) | private Deck parseMetaDeck(Map<String, Object> map) {
method parseStandardDeck (line 225) | private Deck parseStandardDeck(String deckName, HeroClass heroClass, M...
method removeCardFromDeck (line 244) | public void removeCardFromDeck(Card card) {
method saveActiveDeck (line 248) | public void saveActiveDeck() {
method saveToJson (line 254) | private void saveToJson(Deck deck) {
method setActiveDeck (line 290) | public void setActiveDeck(Deck activeDeck) {
method setActiveDeckValidator (line 294) | public void setActiveDeckValidator(IDeckValidator deckValidator) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeleteDeckCommand.java
class DeleteDeckCommand (line 8) | public class DeleteDeckCommand extends SimpleCommand<GameNotification> {
method execute (line 10) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/FillDeckWithRandomCardsCommand.java
class FillDeckWithRandomCardsCommand (line 15) | public class FillDeckWithRandomCardsCommand extends SimpleCommand<GameNo...
method execute (line 19) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/FilterCardsCommand.java
class FilterCardsCommand (line 14) | public class FilterCardsCommand extends SimpleCommand<GameNotification> {
method filterByFormat (line 16) | private static List<Card> filterByFormat(List<Card> collection, DeckFo...
method filterBySet (line 25) | private static List<Card> filterBySet(List<Card> collection, CardSet s...
method filterByText (line 33) | private static List<Card> filterByText(List<Card> collection, String t...
method execute (line 43) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/ImportDeckCommand.java
class ImportDeckCommand (line 12) | public class ImportDeckCommand extends SimpleCommand<GameNotification> {
method execute (line 14) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/LoadDeckFormatsCommand.java
class LoadDeckFormatsCommand (line 11) | public class LoadDeckFormatsCommand extends SimpleCommand<GameNotificati...
method execute (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/LoadDecksCommand.java
class LoadDecksCommand (line 11) | public class LoadDecksCommand extends SimpleCommand<GameNotification> {
method execute (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/RemoveCardFromDeckCommand.java
class RemoveCardFromDeckCommand (line 8) | public class RemoveCardFromDeckCommand extends SimpleCommand<GameNotific...
method execute (line 10) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/SaveDeckCommand.java
class SaveDeckCommand (line 7) | public class SaveDeckCommand extends SimpleCommand<GameNotification> {
method execute (line 9) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/SetActiveDeckCommand.java
class SetActiveDeckCommand (line 10) | public class SetActiveDeckCommand extends SimpleCommand<GameNotification> {
method execute (line 12) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/HearthHeadImporter.java
class HearthHeadImporter (line 20) | public class HearthHeadImporter implements IDeckImporter {
method importFrom (line 23) | @Override
method getCardIds (line 34) | private List<String> getCardIds(Document doc){
method parse (line 55) | private Deck parse(String url) throws IOException {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/HearthPwnImporter.java
class HearthPwnImporter (line 23) | public class HearthPwnImporter implements IDeckImporter {
method extractId (line 27) | private String extractId(String url) {
method getExportUrl (line 42) | private String getExportUrl(String url) {
method importFrom (line 48) | @Override
method parse (line 78) | private Deck parse(String htmlContent) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/IDeckImporter.java
type IDeckImporter (line 5) | public interface IDeckImporter {
method importFrom (line 7) | Deck importFrom(String uri);
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/IcyVeinsImporter.java
class IcyVeinsImporter (line 26) | public class IcyVeinsImporter implements IDeckImporter {
method importFrom (line 30) | @Override
method parse (line 60) | private Deck parse(String htmlContent) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/ImporterFactory.java
class ImporterFactory (line 3) | public class ImporterFactory {
method createDeckImporter (line 5) | public IDeckImporter createDeckImporter(String url)
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/TempostormImporter.java
class TempostormImporter (line 25) | public class TempostormImporter implements IDeckImporter{
method parse (line 29) | Deck parse(JsonObject root)
method convertUrl (line 77) | String convertUrl(String url)
method importFrom (line 90) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/AddDeckToMetaDeckCommand.java
class AddDeckToMetaDeckCommand (line 10) | public class AddDeckToMetaDeckCommand extends SimpleCommand<GameNotifica...
method execute (line 12) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/MetaDeckListView.java
class MetaDeckListView (line 17) | public class MetaDeckListView extends VBox implements EventHandler<Mouse...
method MetaDeckListView (line 22) | public MetaDeckListView() {
method displayDecks (line 36) | public void displayDecks(List<Deck> decks) {
method handle (line 46) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/MetaDeckView.java
class MetaDeckView (line 20) | public class MetaDeckView extends BorderPane {
method MetaDeckView (line 25) | public MetaDeckView() {
method deckChanged (line 39) | public void deckChanged(MetaDeck metaDeck) {
method displayDecks (line 46) | public void displayDecks(List<Deck> decks) {
FILE: app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/RemoveDeckFromMetaDeckCommand.java
class RemoveDeckFromMetaDeckCommand (line 10) | public class RemoveDeckFromMetaDeckCommand extends SimpleCommand<GameNot...
method execute (line 12) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/DialogMediator.java
class DialogMediator (line 18) | public class DialogMediator extends Mediator<GameNotification> {
method DialogMediator (line 26) | public DialogMediator() {
method handleNotification (line 30) | @Override
method listNotificationInterests (line 52) | @Override
method displayErrorMessage (line 62) | private void displayErrorMessage(String header, String message) {
method showModalDialog (line 70) | private void showModalDialog(Node content) {
method showUserDialog (line 74) | private void showUserDialog(DialogNotification notification) {
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/DialogNotification.java
class DialogNotification (line 6) | public class DialogNotification extends Notification<GameNotification> {
method DialogNotification (line 13) | public DialogNotification(String title, String message, DialogType dia...
method getDialogType (line 20) | public DialogType getDialogType() {
method getHandler (line 24) | public IDialogListener getHandler() {
method getMessage (line 28) | public String getMessage() {
method getTitle (line 32) | public String getTitle() {
method setHandler (line 36) | public void setHandler(IDialogListener handler) {
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/DialogResult.java
type DialogResult (line 3) | public enum DialogResult {
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/DialogType.java
type DialogType (line 3) | public enum DialogType {
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/IDialogListener.java
type IDialogListener (line 3) | public interface IDialogListener {
method onDialogClosed (line 5) | void onDialogClosed(DialogResult result);
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/ModalDialog.java
class ModalDialog (line 11) | public class ModalDialog extends StackPane {
method ModalDialog (line 13) | public ModalDialog(Window parent, Node content) {
FILE: app/src/main/java/net/demilich/metastone/gui/dialog/UserDialog.java
class UserDialog (line 15) | public class UserDialog extends BorderPane implements EventHandler<Actio...
method UserDialog (line 34) | public UserDialog(String title, String message, DialogType dialogType) {
method handle (line 53) | @Override
method setDialogHandler (line 62) | public void setDialogHandler(IDialogListener dialogHandler) {
method setDialogResult (line 66) | private void setDialogResult(DialogResult result) {
FILE: app/src/main/java/net/demilich/metastone/gui/gameconfig/PlayerConfigView.java
class PlayerConfigView (line 42) | public class PlayerConfigView extends VBox {
method PlayerConfigView (line 70) | public PlayerConfigView(PlayerConfigType selectionHint) {
method filterDecks (line 94) | private void filterDecks() {
method getPlayerConfig (line 126) | public PlayerConfig getPlayerConfig() {
method injectDecks (line 130) | public void injectDecks(List<Deck> decks) {
method onBehaviourChanged (line 136) | private void onBehaviourChanged(ObservableValue<? extends IBehaviour> ...
method onHideCardBoxChanged (line 145) | private void onHideCardBoxChanged(ObservableValue<? extends Boolean> o...
method selectHero (line 149) | private void selectHero(HeroCard heroCard) {
method setupBehaviours (line 157) | public void setupBehaviours() {
method setupHeroes (line 179) | public void setupHeroes() {
method setupHideCardsBox (line 193) | private void setupHideCardsBox(PlayerConfigType configType) {
method setDeckFormat (line 201) | public void setDeckFormat(DeckFormat newDeckFormat) {
FILE: app/src/main/java/net/demilich/metastone/gui/main/ApplicationMediator.java
class ApplicationMediator (line 20) | public class ApplicationMediator extends Mediator<GameNotification> {
method ApplicationMediator (line 26) | public ApplicationMediator() {
method handleNotification (line 30) | @Override
method listNotificationInterests (line 50) | @Override
method removeOtherViews (line 60) | private void removeOtherViews() {
FILE: app/src/main/java/net/demilich/metastone/gui/mainmenu/MainMenuMediator.java
class MainMenuMediator (line 16) | public class MainMenuMediator extends Mediator<GameNotification> {
method MainMenuMediator (line 22) | public MainMenuMediator() {
method handleNotification (line 27) | @Override
method listNotificationInterests (line 54) | @Override
method onRegister (line 66) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/mainmenu/MainMenuView.java
class MainMenuView (line 17) | public class MainMenuView extends BorderPane {
method MainMenuView (line 43) | public MainMenuView() {
method openDonation (line 81) | private void openDonation(ActionEvent event) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/GameBoardView.java
class GameBoardView (line 32) | public class GameBoardView extends BorderPane {
method GameBoardView (line 68) | public GameBoardView() {
method checkForWinner (line 119) | private void checkForWinner(GameContext context) {
method createSummonHelper (line 133) | private Button createSummonHelper() {
method disableTargetSelection (line 144) | public void disableTargetSelection() {
method enableSpellTargets (line 159) | private void enableSpellTargets(final HumanTargetOptions targetOptions) {
method enableSummonTargets (line 179) | private void enableSummonTargets(final HumanTargetOptions targetOption...
method enableTargetSelection (line 200) | public void enableTargetSelection(final HumanTargetOptions targetOptio...
method getToken (line 210) | public GameToken getToken(Entity entity) {
method hideCenterMessage (line 214) | private void hideCenterMessage() {
method setCenterMessage (line 218) | private void setCenterMessage(String message) {
method showAnimations (line 223) | public void showAnimations(GameContext context) {
method updateGameState (line 227) | public void updateGameState(GameContext context) {
method updateHandCards (line 247) | private void updateHandCards(GameContext context, Player player, HandC...
method updateSummonTokens (line 262) | private void updateSummonTokens(Player player, SummonToken[] summonTok...
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/GameContextVisualizable.java
class GameContextVisualizable (line 16) | public class GameContextVisualizable extends GameContext {
method GameContextVisualizable (line 22) | public GameContextVisualizable(Player player1, Player player2, GameLog...
method acceptAction (line 26) | protected boolean acceptAction(GameAction nextAction) {
method fireGameEvent (line 39) | @Override
method getGameEvents (line 48) | public synchronized List<GameEvent> getGameEvents() {
method isBlockedByAnimation (line 52) | public boolean isBlockedByAnimation() {
method onGameStateChanged (line 56) | @Override
method setBlockedByAnimation (line 74) | public void setBlockedByAnimation(boolean blockedByAnimation) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/GameToken.java
class GameToken (line 23) | public class GameToken extends BorderPane {
method GameToken (line 29) | public GameToken(String fxml) {
method createTargetButton (line 43) | private void createTargetButton() {
method getAnchor (line 65) | public StackPane getAnchor() {
method hideTargetMarker (line 69) | public void hideTargetMarker() {
method setScoreValue (line 73) | protected void setScoreValue(Group group, int value) {
method setScoreValue (line 77) | protected void setScoreValue(Group group, int value, int baseValue) {
method setScoreValue (line 85) | protected void setScoreValue(Group group, int value, int baseValue, in...
method setScoreValueLowerIsBetter (line 95) | protected void setScoreValueLowerIsBetter(Group group, int value, int ...
method showTargetMarker (line 105) | public void showTargetMarker(EventHandler<MouseEvent> clickedHander) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/HeroToken.java
class HeroToken (line 24) | public class HeroToken extends GameToken {
method HeroToken (line 63) | public HeroToken() {
method highlight (line 68) | public void highlight(boolean highlight) {
method setHero (line 79) | public void setHero(Player player) {
method updateArmor (line 102) | private void updateArmor(int armor) {
method updateHeroPower (line 109) | private void updateHeroPower(Hero hero) {
method updateHeroPowerCost (line 120) | public void updateHeroPowerCost(GameContext context, Player player) {
method updateSecrets (line 124) | private void updateSecrets(Player player) {
method updateStatus (line 147) | private void updateStatus(Hero hero) {
method updateWeapon (line 151) | private void updateWeapon(Weapon weapon) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/HumanActionPromptView.java
class HumanActionPromptView (line 34) | public class HumanActionPromptView extends VBox {
method getActionString (line 36) | private static String getActionString(GameContext context, GameAction ...
method HumanActionPromptView (line 90) | public HumanActionPromptView() {
method createActionButton (line 101) | private Node createActionButton(final ActionGroup actionGroup, HumanAc...
method createActionButtons (line 166) | private Collection<Node> createActionButtons(HumanActionOptions option...
method groupActions (line 175) | private Collection<ActionGroup> groupActions(HumanActionOptions option...
method matchesExistingGroup (line 186) | private boolean matchesExistingGroup(GameAction action, Collection<Act...
method setActions (line 196) | public void setActions(HumanActionOptions options) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/HumanMulliganView.java
class HumanMulliganView (line 24) | public class HumanMulliganView extends BorderPane implements EventHandle...
class MulliganEntry (line 26) | private class MulliganEntry {
method MulliganEntry (line 32) | public MulliganEntry(ImageView icon) {
method HumanMulliganView (line 45) | public HumanMulliganView(HumanMulliganOptions options) {
method displayCards (line 61) | private void displayCards(final HumanMulliganOptions options) {
method handle (line 94) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/LoadingBoardView.java
class LoadingBoardView (line 10) | public class LoadingBoardView extends BorderPane {
method LoadingBoardView (line 15) | public LoadingBoardView() {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/PlayModeMediator.java
class PlayModeMediator (line 18) | public class PlayModeMediator extends Mediator<GameNotification>implemen...
method PlayModeMediator (line 25) | public PlayModeMediator() {
method handle (line 31) | @Override
method handleNotification (line 40) | @Override
method listNotificationInterests (line 68) | @Override
method onRegister (line 81) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/PlayModeView.java
class PlayModeView (line 16) | public class PlayModeView extends BorderPane {
method PlayModeView (line 34) | public PlayModeView() {
method disableTargetSelection (line 58) | public void disableTargetSelection() {
method enableTargetSelection (line 63) | public void enableTargetSelection(HumanTargetOptions targetOptions) {
method getActionPromptView (line 67) | public HumanActionPromptView getActionPromptView() {
method showAnimations (line 71) | public void showAnimations(GameContext context) {
method updateGameState (line 75) | public void updateGameState(GameContext context) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/StartGameCommand.java
class StartGameCommand (line 14) | public class StartGameCommand extends SimpleCommand<GameNotification> {
method execute (line 16) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/SummonToken.java
class SummonToken (line 19) | public class SummonToken extends GameToken {
method SummonToken (line 45) | public SummonToken() {
method setSummon (line 54) | public void setSummon(Summon summon) {
method visualizeStatus (line 69) | private void visualizeStatus(Summon summon) {
method visualizeStealth (line 84) | private void visualizeStealth(Summon summon) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/AnimationCompletedCommand.java
class AnimationCompletedCommand (line 7) | public class AnimationCompletedCommand extends SimpleCommand<GameNotific...
method execute (line 9) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/AnimationLockCommand.java
class AnimationLockCommand (line 8) | public class AnimationLockCommand extends SimpleCommand<GameNotification> {
method execute (line 10) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/AnimationProxy.java
class AnimationProxy (line 7) | public class AnimationProxy extends Proxy<GameNotification> {
method AnimationProxy (line 14) | public AnimationProxy() {
method animationCompleted (line 18) | public void animationCompleted() {
method animationStarted (line 24) | public void animationStarted() {
method getContext (line 28) | public GameContextVisualizable getContext() {
method setContext (line 32) | public void setContext(GameContextVisualizable context) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/AnimationStartedCommand.java
class AnimationStartedCommand (line 7) | public class AnimationStartedCommand extends SimpleCommand<GameNotificat...
method execute (line 9) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/CardPlayedToken.java
class CardPlayedToken (line 14) | public class CardPlayedToken {
method CardPlayedToken (line 19) | public CardPlayedToken(GameBoardView boardView, Card card) {
method onComplete (line 40) | private void onComplete(ActionEvent event) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/CardRevealedToken.java
class CardRevealedToken (line 14) | public class CardRevealedToken {
method CardRevealedToken (line 19) | public CardRevealedToken(GameBoardView boardView, Card card, double de...
method secondTransition (line 38) | private void secondTransition(ActionEvent event) {
method nextTransition (line 46) | private void nextTransition(ActionEvent event) {
method onComplete (line 54) | private void onComplete(ActionEvent event) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/DamageEventVisualizer.java
class DamageEventVisualizer (line 11) | public class DamageEventVisualizer implements IGameEventVisualizer {
method visualizeEvent (line 15) | @Override
class HitInfo (line 41) | private class HitInfo {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/DamageNumber.java
class DamageNumber (line 17) | public class DamageNumber extends StackPane {
method DamageNumber (line 21) | public DamageNumber(String text, GameToken parent, int successiveHits) {
method onComplete (line 52) | private void onComplete(ActionEvent event) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/EventVisualizerDispatcher.java
class EventVisualizerDispatcher (line 12) | public class EventVisualizerDispatcher {
method visualize (line 24) | public void visualize(GameContextVisualizable gameContext, GameBoardVi...
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/HealEventVisualizer.java
class HealEventVisualizer (line 9) | public class HealEventVisualizer implements IGameEventVisualizer {
method visualizeEvent (line 11) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/HealingNumber.java
class HealingNumber (line 13) | public class HealingNumber extends Text {
method HealingNumber (line 17) | public HealingNumber(String text, GameToken parent) {
method onComplete (line 36) | private void onComplete(ActionEvent event) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/IAnimationListener.java
type IAnimationListener (line 3) | public interface IAnimationListener {
method animationCompleted (line 5) | public void animationCompleted();
method animationStarted (line 7) | public void animationStarted();
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/IGameEventVisualizer.java
type IGameEventVisualizer (line 7) | public interface IGameEventVisualizer {
method visualizeEvent (line 9) | void visualizeEvent(GameContext gameContext, GameEvent event, GameBoar...
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/JoustToken.java
class JoustToken (line 15) | public class JoustToken {
method JoustToken (line 20) | public JoustToken(GameBoardView boardView, Card card, boolean up, bool...
method onComplete (line 51) | private void onComplete(ActionEvent event) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/JoustVisualizer.java
class JoustVisualizer (line 9) | public class JoustVisualizer implements IGameEventVisualizer {
method visualizeEvent (line 11) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/PlayCardVisualizer.java
class PlayCardVisualizer (line 9) | public class PlayCardVisualizer implements IGameEventVisualizer {
method visualizeEvent (line 11) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/animation/RevealCardVisualizer.java
class RevealCardVisualizer (line 9) | public class RevealCardVisualizer implements IGameEventVisualizer {
method visualizeEvent (line 11) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/config/PlayModeConfigMediator.java
class PlayModeConfigMediator (line 14) | public class PlayModeConfigMediator extends Mediator<GameNotification> {
method PlayModeConfigMediator (line 20) | public PlayModeConfigMediator() {
method handleNotification (line 25) | @Override
method listNotificationInterests (line 54) | @Override
method onRegister (line 63) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/config/PlayModeConfigView.java
class PlayModeConfigView (line 25) | public class PlayModeConfigView extends BorderPane implements EventHandl...
method PlayModeConfigView (line 44) | public PlayModeConfigView() {
method setupDeckFormats (line 71) | private void setupDeckFormats() {
method setDeckFormats (line 82) | private void setDeckFormats(DeckFormat newDeckFormat) {
method handle (line 87) | @Override
method injectDecks (line 101) | public void injectDecks(List<Deck> decks) {
method injectDeckFormats (line 106) | public void injectDeckFormats(List<DeckFormat> deckFormats) {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/config/PlayerConfigType.java
type PlayerConfigType (line 3) | public enum PlayerConfigType {
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/config/RequestDeckFormatsCommand.java
class RequestDeckFormatsCommand (line 11) | public class RequestDeckFormatsCommand extends SimpleCommand<GameNotific...
method execute (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/playmode/config/RequestDecksCommand.java
class RequestDecksCommand (line 11) | public class RequestDecksCommand extends SimpleCommand<GameNotification> {
method execute (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/CardCollectionEditor.java
class CardCollectionEditor (line 20) | public class CardCollectionEditor extends SandboxEditor {
class CardStringConverter (line 22) | private class CardStringConverter extends StringConverter<Card> {
method fromString (line 24) | @Override
method toString (line 29) | @Override
method CardCollectionEditor (line 61) | public CardCollectionEditor(String title, CardCollection cardCollectio...
method handleAddCardButton (line 84) | private void handleAddCardButton(ActionEvent actionEvent) {
method handleCancelButton (line 90) | private void handleCancelButton(ActionEvent actionEvent) {
method handleEditableCardListChanged (line 94) | private void handleEditableCardListChanged(Change<? extends Card> chan...
method handleOkButton (line 100) | private void handleOkButton(ActionEvent actionEvent) {
method handleRemoveCardButton (line 109) | private void handleRemoveCardButton(ActionEvent actionEvent) {
method onFilterTextChanged (line 113) | private void onFilterTextChanged(ObservableValue<? extends String> obs...
method populateCatalogueView (line 117) | private void populateCatalogueView(String filter) {
method populateEditableView (line 130) | private void populateEditableView(CardCollection cardCollection) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/CardPanel.java
class CardPanel (line 16) | public class CardPanel extends VBox {
method CardPanel (line 26) | public CardPanel() {
method handleEditDeckButton (line 41) | private void handleEditDeckButton(ActionEvent actionEvent) {
method handleEditHandButton (line 48) | private void handleEditHandButton(ActionEvent actionEvent) {
method onDeckFinishedEditing (line 55) | private void onDeckFinishedEditing(CardCollection cardCollection) {
method onHandFinishedEditing (line 59) | private void onHandFinishedEditing(CardCollection cardCollection) {
method onPlayerSelectionChanged (line 63) | public void onPlayerSelectionChanged(Player selectedPlayer) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/EntityEditor.java
class EntityEditor (line 24) | public class EntityEditor extends SandboxEditor {
class PairKeyFactory (line 26) | private class PairKeyFactory implements Callback<TableColumn.CellDataF...
method call (line 27) | @Override
class PairValueCell (line 33) | private class PairValueCell extends TableCell<GameTagEntry, Object> {
method updateItem (line 34) | @Override
class PairValueFactory (line 78) | private class PairValueFactory implements Callback<TableColumn.CellDat...
method call (line 79) | @Override
method EntityEditor (line 99) | public EntityEditor(Entity entity, ICallback callback) {
method addTagIfMissing (line 122) | private void addTagIfMissing(Entity entity, Attribute tag, Object defa...
method addTagsIfMissing (line 129) | private void addTagsIfMissing(Entity entity) {
method getNumericTextField (line 155) | private IntegerTextField getNumericTextField() {
method handleCancelButton (line 161) | private void handleCancelButton(ActionEvent actionEvent) {
method handleOkButton (line 165) | private void handleOkButton(ActionEvent actionEvent) {
method populateTable (line 176) | private void populateTable(Entity entity) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/GameTagEntry.java
class GameTagEntry (line 7) | public class GameTagEntry {
method GameTagEntry (line 13) | public GameTagEntry(Attribute tag, Object value) {
method getName (line 19) | public String getName() {
method getTag (line 23) | public Attribute getTag() {
method getValue (line 27) | public Object getValue() {
method getValueBool (line 31) | public boolean getValueBool() {
method getValueInt (line 35) | public int getValueInt() {
method getValueType (line 39) | public TagValueType getValueType() {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/ICardCollectionEditingListener.java
type ICardCollectionEditingListener (line 5) | public interface ICardCollectionEditingListener {
method onFinishedEditing (line 7) | void onFinishedEditing(CardCollection cardCollection);
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/MinionPanel.java
class MinionPanel (line 26) | public class MinionPanel extends VBox {
method MinionPanel (line 39) | public MinionPanel() {
method handleKillMinionButton (line 57) | private void handleKillMinionButton(ActionEvent actionEvent) {
method handleSilenceButton (line 62) | private void handleSilenceButton(ActionEvent actionEvent) {
method handleSpawnMinionButton (line 67) | private void handleSpawnMinionButton(ActionEvent actionEvent) {
method onMinionFilterChanged (line 72) | private void onMinionFilterChanged(ObservableValue<? extends String> o...
method populateMinions (line 76) | private void populateMinions(String filter) {
method setContext (line 95) | public void setContext(GameContext context) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/PlayerPanel.java
class PlayerPanel (line 24) | public class PlayerPanel extends VBox {
class PlayerStringConverter (line 26) | private class PlayerStringConverter extends StringConverter<Player> {
method fromString (line 28) | @Override
method toString (line 33) | @Override
method PlayerPanel (line 55) | public PlayerPanel() {
method handleCurrentManaChanged (line 75) | private void handleCurrentManaChanged(ObservableValue<? extends Number...
method handleEditEntityButton (line 84) | private void handleEditEntityButton(ActionEvent actionEvent) {
method handleMaxManaChanged (line 89) | private void handleMaxManaChanged(ObservableValue<? extends Number> ov...
method handlePlayerChanged (line 98) | private void handlePlayerChanged(ObservableValue<? extends Player> ov,...
method populateManaBoxes (line 104) | private void populateManaBoxes() {
method setContext (line 120) | public void setContext(GameContext context) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxEditor.java
class SandboxEditor (line 11) | public class SandboxEditor extends BorderPane {
method SandboxEditor (line 22) | public SandboxEditor(String fxmlFile) {
method setTitle (line 34) | protected void setTitle(String title) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxModeConfigView.java
class SandboxModeConfigView (line 25) | public class SandboxModeConfigView extends BorderPane {
method SandboxModeConfigView (line 44) | public SandboxModeConfigView() {
method setupDeckFormats (line 71) | private void setupDeckFormats() {
method setDeckFormats (line 82) | private void setDeckFormats(DeckFormat newDeckFormat) {
method handleBackButton (line 87) | private void handleBackButton(ActionEvent event) {
method handleStartButton (line 91) | private void handleStartButton(ActionEvent event) {
method injectDecks (line 100) | public void injectDecks(List<Deck> decks) {
method injectDeckFormats (line 105) | public void injectDeckFormats(List<DeckFormat> deckFormats) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxModeMediator.java
class SandboxModeMediator (line 20) | public class SandboxModeMediator extends Mediator<GameNotification>imple...
method SandboxModeMediator (line 27) | public SandboxModeMediator() {
method handle (line 33) | @Override
method handleNotification (line 42) | @SuppressWarnings("unchecked")
method listNotificationInterests (line 87) | @Override
method onRegister (line 103) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxModeView.java
class SandboxModeView (line 24) | public class SandboxModeView extends BorderPane {
method SandboxModeView (line 42) | public SandboxModeView() {
method disableTargetSelection (line 70) | public void disableTargetSelection() {
method enableTargetSelection (line 75) | public void enableTargetSelection(HumanTargetOptions targetOptions) {
method getActionPromptView (line 79) | public HumanActionPromptView getActionPromptView() {
method getBoardView (line 83) | public GameBoardView getBoardView() {
method onPlayerSelectionChanged (line 87) | public void onPlayerSelectionChanged(Player selectedPlayer) {
method showAnimations (line 91) | public void showAnimations(GameContext context) {
method startPlayMode (line 95) | private void startPlayMode(ActionEvent actionEvent) {
method stopPlayMode (line 105) | private void stopPlayMode(ActionEvent actionEvent) {
method updateSandbox (line 115) | public void updateSandbox(GameContext context) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxProxy.java
class SandboxProxy (line 8) | public class SandboxProxy extends Proxy<GameNotification> {
method SandboxProxy (line 15) | public SandboxProxy() {
method getSandbox (line 19) | public GameContext getSandbox() {
method getSelectedPlayer (line 23) | public Player getSelectedPlayer() {
method setSandbox (line 27) | public void setSandbox(GameContext sandbox) {
method setSelectedPlayer (line 31) | public void setSelectedPlayer(Player selectedPlayer) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/ToolboxView.java
class ToolboxView (line 11) | public class ToolboxView extends ToolBar {
method ToolboxView (line 17) | public ToolboxView() {
method onPlayerSelectionChanged (line 38) | public void onPlayerSelectionChanged(Player selectedPlayer) {
method setContext (line 42) | public void setContext(GameContext context) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/EditEntityAction.java
class EditEntityAction (line 12) | public class EditEntityAction extends GameAction {
method EditEntityAction (line 14) | public EditEntityAction() {
method execute (line 19) | @Override
method getPromptText (line 27) | @Override
method isSameActionGroup (line 32) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/KillAction.java
class KillAction (line 9) | public class KillAction extends GameAction {
method KillAction (line 11) | public KillAction() {
method execute (line 16) | @Override
method getPromptText (line 22) | @Override
method isSameActionGroup (line 27) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/SetManaAction.java
class SetManaAction (line 8) | public class SetManaAction extends GameAction {
method SetManaAction (line 13) | public SetManaAction(int playerId, int mana) {
method execute (line 19) | @Override
method getPromptText (line 25) | @Override
method isSameActionGroup (line 30) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/SetMaxManaAction.java
class SetMaxManaAction (line 8) | public class SetMaxManaAction extends GameAction {
method SetMaxManaAction (line 13) | public SetMaxManaAction(int playerId, int mana) {
method execute (line 19) | @Override
method getPromptText (line 25) | @Override
method isSameActionGroup (line 30) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/SilenceAction.java
class SilenceAction (line 9) | public class SilenceAction extends GameAction {
method SilenceAction (line 11) | public SilenceAction() {
method execute (line 16) | @Override
method getPromptText (line 22) | @Override
method isSameActionGroup (line 27) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/CreateNewSandboxCommand.java
class CreateNewSandboxCommand (line 16) | public class CreateNewSandboxCommand extends SimpleCommand<GameNotificat...
method execute (line 18) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/ModifyPlayerDeckCommand.java
class ModifyPlayerDeckCommand (line 12) | public class ModifyPlayerDeckCommand extends SimpleCommand<GameNotificat...
method execute (line 14) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/ModifyPlayerHandCommand.java
class ModifyPlayerHandCommand (line 12) | public class ModifyPlayerHandCommand extends SimpleCommand<GameNotificat...
method execute (line 14) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/PerformActionCommand.java
class PerformActionCommand (line 18) | public class PerformActionCommand extends SimpleCommand<GameNotification> {
method execute (line 20) | @Override
method performAction (line 46) | private void performAction(GameAction action) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/SelectPlayerCommand.java
class SelectPlayerCommand (line 9) | public class SelectPlayerCommand extends SimpleCommand<GameNotification> {
method execute (line 11) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/SpawnMinionCommand.java
class SpawnMinionCommand (line 21) | public class SpawnMinionCommand extends SimpleCommand<GameNotification> {
method execute (line 25) | @Override
method spawnMinion (line 46) | private void spawnMinion(GameAction action) {
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/StartPlaySandboxCommand.java
class StartPlaySandboxCommand (line 9) | public class StartPlaySandboxCommand extends SimpleCommand<GameNotificat...
method execute (line 11) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/StopPlaySandboxCommand.java
class StopPlaySandboxCommand (line 9) | public class StopPlaySandboxCommand extends SimpleCommand<GameNotificati...
method execute (line 11) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/PlayerConfigView.java
class PlayerConfigView (line 5) | public class PlayerConfigView extends net.demilich.metastone.gui.gamecon...
method PlayerConfigView (line 7) | public PlayerConfigView() {
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/PlayerInfoView.java
class PlayerInfoView (line 14) | public class PlayerInfoView extends Pane {
method PlayerInfoView (line 28) | public PlayerInfoView() {
method setInfo (line 40) | public void setInfo(PlayerConfig playerConfig) {
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulateGamesCommand.java
class SimulateGamesCommand (line 27) | public class SimulateGamesCommand extends SimpleCommand<GameNotification> {
class PlayGameTask (line 29) | private class PlayGameTask implements Callable<Void> {
method PlayGameTask (line 33) | public PlayGameTask(GameConfig gameConfig) {
method call (line 37) | @Override
method execute (line 64) | @Override
method onGameComplete (line 129) | private void onGameComplete(GameConfig gameConfig, GameContext context) {
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulationMediator.java
class SimulationMediator (line 17) | public class SimulationMediator extends Mediator<GameNotification> {
method SimulationMediator (line 27) | public SimulationMediator() {
method handleNotification (line 34) | @Override
method listNotificationInterests (line 77) | @Override
method onRegister (line 88) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulationModeConfigView.java
class SimulationModeConfigView (line 24) | public class SimulationModeConfigView extends BorderPane implements Even...
method SimulationModeConfigView (line 46) | public SimulationModeConfigView() {
method setupDeckFormats (line 74) | private void setupDeckFormats() {
method setDeckFormats (line 85) | private void setDeckFormats(DeckFormat newDeckFormat) {
method handle (line 90) | @Override
method injectDecks (line 104) | public void injectDecks(List<Deck> decks) {
method injectDeckFormats (line 109) | public void injectDeckFormats(List<DeckFormat> deckFormats) {
method setupNumberOfGamesBox (line 116) | private void setupNumberOfGamesBox() {
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulationResult.java
class SimulationResult (line 7) | public class SimulationResult {
method SimulationResult (line 15) | public SimulationResult(GameConfig config) {
method calculateMetaStatistics (line 20) | public void calculateMetaStatistics() {
method calculateMetaStatistics (line 25) | private void calculateMetaStatistics(GameStatistics statistics) {
method getConfig (line 35) | public GameConfig getConfig() {
method getDuration (line 39) | public long getDuration() {
method getNumberOfGames (line 43) | public int getNumberOfGames() {
method getPlayer1Stats (line 47) | public GameStatistics getPlayer1Stats() {
method getPlayer2Stats (line 51) | public GameStatistics getPlayer2Stats() {
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulationResultView.java
class SimulationResultView (line 30) | public class SimulationResultView extends BorderPane {
method getStatName (line 32) | private static String getStatName(Statistic stat) {
method SimulationResultView (line 90) | public SimulationResultView() {
method getAverageStatString (line 112) | private String getAverageStatString(Statistic stat, GameStatistics pla...
method getFavouriteCardName (line 124) | private String getFavouriteCardName(GameStatistics stats, CardType car...
method getStatString (line 152) | private String getStatString(Statistic stat, GameStatistics playerStat...
method showSimulationResult (line 163) | @SuppressWarnings({ "rawtypes", "unchecked" })
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/StatEntry.java
class StatEntry (line 6) | public class StatEntry {
method StatEntry (line 11) | public StatEntry() {
method StatEntry (line 14) | public StatEntry(String statName, String player1Value, String player2V...
method getPlayer1Value (line 20) | public String getPlayer1Value() {
method getPlayer2Value (line 24) | public String getPlayer2Value() {
method getStatName (line 28) | public String getStatName() {
method player1ValueProperty (line 32) | public StringProperty player1ValueProperty() {
method player2ValueProperty (line 36) | public StringProperty player2ValueProperty() {
method setPlayer1Value (line 40) | public void setPlayer1Value(String value) {
method setPlayer2Value (line 44) | public void setPlayer2Value(String value) {
method setStatName (line 48) | public void setStatName(String value) {
method statNameProperty (line 52) | public StringProperty statNameProperty() {
FILE: app/src/main/java/net/demilich/metastone/gui/simulationmode/WaitForSimulationView.java
class WaitForSimulationView (line 11) | public class WaitForSimulationView extends BorderPane {
method WaitForSimulationView (line 19) | public WaitForSimulationView() {
method update (line 32) | public void update(int gamesCompleted, int gamesTotal) {
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/PerformTrainingCommand.java
class PerformTrainingCommand (line 22) | public class PerformTrainingCommand extends SimpleCommand<GameNotificati...
method execute (line 29) | @Override
method onGameComplete (line 94) | private void onGameComplete(TrainingConfig config, GameContext complet...
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/RequestTrainingDataCommand.java
class RequestTrainingDataCommand (line 13) | public class RequestTrainingDataCommand extends SimpleCommand<GameNotifi...
method execute (line 17) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/SaveTrainingDataCommand.java
class SaveTrainingDataCommand (line 8) | public class SaveTrainingDataCommand extends SimpleCommand<GameNotificat...
method execute (line 10) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingConfig.java
class TrainingConfig (line 9) | public class TrainingConfig {
method TrainingConfig (line 15) | public TrainingConfig(Deck deckToTrain) {
method getDecks (line 19) | public List<Deck> getDecks() {
method getDeckToTrain (line 23) | public Deck getDeckToTrain() {
method getNumberOfGames (line 27) | public int getNumberOfGames() {
method getRandomDeck (line 31) | public Deck getRandomDeck() {
method setNumberOfGames (line 35) | public void setNumberOfGames(int numberOfGames) {
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingConfigView.java
class TrainingConfigView (line 25) | public class TrainingConfigView extends BorderPane {
method TrainingConfigView (line 46) | public TrainingConfigView() {
method handleAddButton (line 72) | private void handleAddButton(ActionEvent event) {
method handleRemoveButton (line 78) | private void handleRemoveButton(ActionEvent event) {
method handleStartButton (line 84) | private void handleStartButton(ActionEvent event) {
method injectDecks (line 95) | public void injectDecks(List<Deck> decks) {
method setupDeckBox (line 108) | private void setupDeckBox() {
method setupNumberOfGamesBox (line 112) | private void setupNumberOfGamesBox() {
method injectDeckFormats (line 123) | public void injectDeckFormats(List<DeckFormat> body) {
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingModeMediator.java
class TrainingModeMediator (line 13) | public class TrainingModeMediator extends Mediator<GameNotification> {
method TrainingModeMediator (line 20) | public TrainingModeMediator() {
method handleNotification (line 26) | @SuppressWarnings("unchecked")
method listNotificationInterests (line 57) | @Override
method onRegister (line 67) | @Override
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingModeView.java
class TrainingModeView (line 17) | public class TrainingModeView extends BorderPane implements EventHandler...
method TrainingModeView (line 33) | public TrainingModeView() {
method handle (line 49) | @Override
method setDeckName (line 56) | public void setDeckName(String deckname) {
method showProgress (line 60) | public void showProgress(TrainingProgressReport progress) {
method startTraining (line 73) | public void startTraining() {
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingProgressReport.java
class TrainingProgressReport (line 3) | public class TrainingProgressReport {
method TrainingProgressReport (line 9) | public TrainingProgressReport(int gamesCompleted, int gamesTotal, int ...
method getGamesCompleted (line 15) | public int getGamesCompleted() {
method getGamesTotal (line 19) | public int getGamesTotal() {
method getGamesWon (line 23) | public int getGamesWon() {
FILE: app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingProxy.java
class TrainingProxy (line 30) | public class TrainingProxy extends Proxy<GameNotification> {
method TrainingProxy (line 40) | public TrainingProxy() {
method getTrainingData (line 56) | public TrainingData getTrainingData(String deckName) {
method loadTrainingData (line 60) | public void loadTrainingData() throws IOException, URISyntaxException {
method saveTrainingData (line 102) | public void saveTrainingData(TrainingData trainingData) {
FILE: app/src/main/java/net/demilich/metastone/tools/CardCreator.java
class CardCreator (line 8) | public class CardCreator extends Application {
method main (line 10) | public static void main(String[] args) {
method start (line 14) | @Override
FILE: app/src/main/java/net/demilich/metastone/tools/CardEditor.java
class CardEditor (line 17) | public abstract class CardEditor extends VBox implements ICardEditor {
method CardEditor (line 19) | public CardEditor(String fxmlFile) {
method fillWithSpells (line 31) | @SuppressWarnings("unchecked")
method getPanel (line 52) | @Override
FILE: app/src/main/java/net/demilich/metastone/tools/EditorMainWindow.java
class EditorMainWindow (line 44) | class EditorMainWindow extends BorderPane {
method getCardId (line 46) | private static String getCardId(CardDesc card) {
method EditorMainWindow (line 125) | public EditorMainWindow() {
method getAttributeValue (line 177) | private Object getAttributeValue(String valueString) {
method onAttributesChanged (line 189) | private void onAttributesChanged() {
method onCardSetChanged (line 208) | private void onCardSetChanged(ObservableValue<? extends CardSet> ov, C...
method onCollectibleChanged (line 212) | private void onCollectibleChanged(ActionEvent event) {
method onDescriptionChanged (line 216) | private void onDescriptionChanged(ObservableValue<? extends String> ov...
method onHeroClassChanged (line 220) | private void onHeroClassChanged(ObservableValue<? extends HeroClass> o...
method onNameChanged (line 224) | private void onNameChanged(ObservableValue<? extends String> ov, Strin...
method onRarityChanged (line 230) | private void onRarityChanged(ObservableValue<? extends Rarity> ov, Rar...
method onSaveButton (line 234) | private void onSaveButton(ActionEvent event) {
method reset (line 238) | private void reset(ActionEvent event) {
method save (line 246) | private void save() {
method setCardEditor (line 271) | private void setCardEditor(ICardEditor cardEditor) {
method setupAttributeBoxes (line 303) | private void setupAttributeBoxes() {
FILE: app/src/main/java/net/demilich/metastone/tools/ICardEditor.java
type ICardEditor (line 6) | public interface ICardEditor {
method getCardDesc (line 8) | public CardDesc getCardDesc();
method getPanel (line 10) | public Node getPanel();
method reset (line 12) | public void reset();
FILE: app/src/main/java/net/demilich/metastone/tools/ITextFieldAction.java
type ITextFieldAction (line 3) | interface ITextFieldAction {
method onChanged (line 5) | public void onChanged(int value);
FILE: app/src/main/java/net/demilich/metastone/tools/IntegerListener.java
class IntegerListener (line 7) | public class IntegerListener implements ChangeListener<String> {
method IntegerListener (line 11) | public IntegerListener(ITextFieldAction action) {
method changed (line 15) | @Override
FILE: app/src/main/java/net/demilich/metastone/tools/MinionCardPanel.java
class MinionCardPanel (line 17) | class MinionCardPanel extends CardEditor {
method MinionCardPanel (line 38) | public MinionCardPanel() {
method getCardDesc (line 60) | @Override
method onBattlecryChanged (line 67) | private void onBattlecryChanged(ObservableValue<? extends Class<? exte...
method onDeathrattleChanged (line 76) | private void onDeathrattleChanged(ObservableValue<? extends Class<? ex...
method onRaceChanged (line 81) | private void onRaceChanged(ObservableValue<? extends Race> ov, Race ol...
method onTargetSelectionChanged (line 85) | private void onTargetSelectionChanged(ObservableValue<? extends Target...
method reset (line 93) | @Override
FILE: app/src/main/java/net/demilich/metastone/tools/SpellCardPanel.java
class SpellCardPanel (line 14) | public class SpellCardPanel extends CardEditor {
method SpellCardPanel (line 23) | public SpellCardPanel() {
method getCardDesc (line 35) | @Override
method onSpellChanged (line 43) | private void onSpellChanged(ObservableValue<? extends Class<? extends ...
method onTargetSelectionChanged (line 48) | private void onTargetSelectionChanged(ObservableValue<? extends Target...
method reset (line 53) | @Override
FILE: app/src/main/java/net/demilich/metastone/tools/SpellDescSerializer.java
class SpellDescSerializer (line 15) | public class SpellDescSerializer implements JsonSerializer<SpellDesc> {
method serialize (line 17) | @Override
FILE: app/src/main/java/net/demilich/metastone/tools/SpellStringConverter.java
class SpellStringConverter (line 6) | public class SpellStringConverter extends StringConverter<Class<? extend...
method fromString (line 8) | @Override
method toString (line 13) | @Override
FILE: app/src/main/java/net/demilich/metastone/tools/WeaponClassPanel.java
class WeaponClassPanel (line 7) | public class WeaponClassPanel extends CardEditor {
method WeaponClassPanel (line 11) | public WeaponClassPanel() {
method getCardDesc (line 15) | @Override
method reset (line 22) | @Override
FILE: cards/src/test/java/net/demilich/metastone/tests/ValidateCards.java
class ValidateCards (line 25) | public class ValidateCards {
method getCardFiles (line 49) | @DataProvider(name = "CardProvider")
method validateCard (line 63) | @Test(dataProvider = "CardProvider")
FILE: game/src/main/java/net/demilich/metastone/game/Attribute.java
type Attribute (line 3) | public enum Attribute {
FILE: game/src/main/java/net/demilich/metastone/game/Environment.java
type Environment (line 3) | public enum Environment {
method customClone (line 20) | public boolean customClone() {
FILE: game/src/main/java/net/demilich/metastone/game/GameContext.java
class GameContext (line 30) | public class GameContext implements Cloneable, IDisposable {
method GameContext (line 56) | public GameContext(Player player1, Player player2, GameLogic logic, De...
method acceptAction (line 67) | protected boolean acceptAction(GameAction nextAction) {
method addCardCostModifier (line 71) | public void addCardCostModifier(CardCostModifier cardCostModifier) {
method addTempCard (line 75) | public void addTempCard(Card card) {
method addTrigger (line 79) | public void addTrigger(IGameEventListener trigger) {
method clone (line 83) | @Override
method dispose (line 123) | @Override
method endGame (line 133) | private void endGame() {
method endTurn (line 151) | public void endTurn() {
method findCardinCollection (line 158) | private Card findCardinCollection(CardCollection cardCollection, int c...
method fireGameEvent (line 167) | public void fireGameEvent(GameEvent gameEvent) {
method gameDecided (line 181) | public boolean gameDecided() {
method getActivePlayer (line 187) | public Player getActivePlayer() {
method getActivePlayerId (line 191) | public int getActivePlayerId() {
method getAdjacentSummons (line 195) | public List<Summon> getAdjacentSummons(Player player, EntityReference ...
method getAutoHeroPowerAction (line 214) | public GameAction getAutoHeroPowerAction() {
method getBoardPosition (line 218) | public int getBoardPosition(Summon summon) {
method getCardById (line 230) | public Card getCardById(String cardId) {
method getCardCostModifiers (line 242) | public List<CardCostModifier> getCardCostModifiers() {
method getDamageStack (line 246) | @SuppressWarnings("unchecked")
method getDeckFormat (line 254) | public DeckFormat getDeckFormat() {
method getEnvironment (line 258) | public HashMap<Environment, Object> getEnvironment() {
method getEventCard (line 262) | public Card getEventCard() {
method getEventTargetStack (line 266) | @SuppressWarnings("unchecked")
method getLeftSummons (line 274) | public List<Summon> getLeftSummons(Player player, EntityReference mini...
method getLogic (line 288) | public GameLogic getLogic() {
method getMinionCount (line 292) | public int getMinionCount(Player player) {
method getSummonCount (line 296) | public int getSummonCount(Player player) {
method getOpponent (line 300) | public Player getOpponent(Player player) {
method getOppositeSummons (line 304) | public List<Summon> getOppositeSummons(Player player, EntityReference ...
method getPendingCard (line 334) | public Card getPendingCard() {
method getPlayer (line 338) | public Player getPlayer(int index) {
method getPlayer1 (line 342) | public Player getPlayer1() {
method getPlayer2 (line 346) | public Player getPlayer2() {
method getPlayers (line 350) | public Player[] getPlayers() {
method getRightSummons (line 354) | public List<Summon> getRightSummons(Player player, EntityReference min...
method getSummonReferenceStack (line 368) | @SuppressWarnings("unchecked")
method getTempCards (line 376) | public CardCollection getTempCards() {
method getTotalMinionCount (line 380) | public int getTotalMinionCount() {
method getTotalSummonCount (line 388) | public int getTotalSummonCount() {
method getTriggersAssociatedWith (line 396) | public List<IGameEventListener> getTriggersAssociatedWith(EntityRefere...
method getTurn (line 400) | public int getTurn() {
method getTurnState (line 404) | public TurnState getTurnState() {
method getValidActions (line 408) | public List<GameAction> getValidActions() {
method getWinningPlayerId (line 415) | public int getWinningPlayerId() {
method hasAutoHeroPower (line 419) | public boolean hasAutoHeroPower() {
method ignoreEvents (line 426) | public boolean ignoreEvents() {
method init (line 430) | public void init() {
method onGameStateChanged (line 438) | protected void onGameStateChanged() {
method performAction (line 441) | private void performAction(int playerId, GameAction gameAction) {
method play (line 446) | public void play() {
method playFromState (line 460) | public void playFromState(){
method playTurn (line 473) | public boolean playTurn() {
method printCurrentTriggers (line 503) | public void printCurrentTriggers() {
method removeTrigger (line 508) | public void removeTrigger(IGameEventListener trigger) {
method removeTriggersAssociatedWith (line 512) | public void removeTriggersAssociatedWith(EntityReference entityReferen...
method resolveCardReference (line 516) | public Card resolveCardReference(CardReference cardReference) {
method resolveSingleTarget (line 539) | public Entity resolveSingleTarget(EntityReference targetKey) {
method resolveTarget (line 546) | public List<Entity> resolveTarget(Player player, Entity source, Entity...
method setEventCard (line 550) | public void setEventCard(Card eventCard) {
method setIgnoreEvents (line 558) | public void setIgnoreEvents(boolean ignoreEvents) {
method setPendingCard (line 562) | public void setPendingCard(Card pendingCard) {
method startTurn (line 570) | protected void startTurn(int playerId) {
method toString (line 578) | @Override
method tryFind (line 617) | public Entity tryFind(EntityReference targetKey) {
FILE: game/src/main/java/net/demilich/metastone/game/Player.java
class Player (line 21) | public class Player extends Entity {
method Player (line 44) | private Player(Player otherPlayer) {
method Player (line 64) | public Player(PlayerConfig config) {
method clone (line 75) | @Override
method getBehaviour (line 80) | public IBehaviour getBehaviour() {
method getCharacters (line 84) | public List<Actor> getCharacters() {
method getDeck (line 91) | public CardCollection getDeck() {
method getDeckName (line 95) | public String getDeckName() {
method getEntityType (line 99) | @Override
method getGraveyard (line 104) | public List<Entity> getGraveyard() {
method getHand (line 108) | public CardCollection getHand() {
method getHero (line 112) | public Hero getHero() {
method getLockedMana (line 116) | public int getLockedMana() {
method getMana (line 120) | public int getMana() {
method getMaxMana (line 124) | public int getMaxMana() {
method getMinions (line 128) | public List<Minion> getMinions() {
method getQuests (line 138) | public HashSet<String> getQuests() {
method getSummons (line 142) | public List<Summon> getSummons() {
method getSecrets (line 146) | public HashSet<String> getSecrets() {
method getSetAsideZone (line 150) | public List<Entity> getSetAsideZone() {
method getStatistics (line 154) | public GameStatistics getStatistics() {
method hideCards (line 158) | public boolean hideCards() {
method setBehaviour (line 162) | public void setBehaviour(IBehaviour behaviour) {
method setHero (line 166) | public void setHero(Hero hero) {
method setHideCards (line 170) | public void setHideCards(boolean hideCards) {
method setLockedMana (line 174) | public void setLockedMana(int lockedMana) {
method setMana (line 178) | public void setMana(int mana) {
method setMaxMana (line 182) | public void setMaxMana(int maxMana) {
method toString (line 186) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/PlayerAttribute.java
type PlayerAttribute (line 3) | public enum PlayerAttribute {
FILE: game/src/main/java/net/demilich/metastone/game/TurnState.java
type TurnState (line 3) | public enum TurnState {
FILE: game/src/main/java/net/demilich/metastone/game/actions/ActionType.java
type ActionType (line 3) | public enum ActionType {
FILE: game/src/main/java/net/demilich/metastone/game/actions/BattlecryAction.java
class BattlecryAction (line 14) | public class BattlecryAction extends GameAction {
method createBattlecry (line 16) | public static BattlecryAction createBattlecry(SpellDesc spell) {
method createBattlecry (line 20) | public static BattlecryAction createBattlecry(SpellDesc spell, TargetS...
method BattlecryAction (line 29) | protected BattlecryAction(SpellDesc spell) {
method canBeExecuted (line 34) | public boolean canBeExecuted(GameContext context, Player player) {
method canBeExecutedOn (line 41) | @Override
method clone (line 55) | @Override
method execute (line 63) | @Override
method getCondition (line 69) | private Condition getCondition() {
method getEntityFilter (line 73) | public EntityFilter getEntityFilter() {
method getPromptText (line 77) | @Override
method getSpell (line 82) | public SpellDesc getSpell() {
method isSameActionGroup (line 86) | @Override
method setCondition (line 91) | public void setCondition(Condition condition) {
method setEntityFilter (line 95) | public void setEntityFilter(Predicate<Entity> entityFilter) {
method toString (line 99) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/DiscoverAction.java
class DiscoverAction (line 15) | public class DiscoverAction extends GameAction {
method createDiscover (line 18) | public static DiscoverAction createDiscover(SpellDesc spell) {
method DiscoverAction (line 30) | protected DiscoverAction(SpellDesc spell) {
method canBeExecuted (line 35) | public boolean canBeExecuted(GameContext context, Player player) {
method canBeExecutedOn (line 42) | @Override
method clone (line 56) | @Override
method execute (line 64) | @Override
method getCard (line 70) | public Card getCard() {
method getCondition (line 74) | private Condition getCondition() {
method getDescription (line 78) | public String getDescription() {
method getEntityFilter (line 82) | public EntityFilter getEntityFilter() {
method getGroupIndex (line 86) | public int getGroupIndex() {
method getName (line 90) | public String getName() {
method getPromptText (line 94) | @Override
method getSpell (line 99) | public SpellDesc getSpell() {
method isSameActionGroup (line 103) | @Override
method setCard (line 108) | public void setCard(Card card) {
method setCondition (line 112) | public void setCondition(Condition condition) {
method setDescription (line 116) | public void setDescription(String description) {
method setEntityFilter (line 120) | public void setEntityFilter(Predicate<Entity> entityFilter) {
method setName (line 124) | public void setName(String name) {
method toString (line 128) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/EndTurnAction.java
class EndTurnAction (line 6) | public class EndTurnAction extends GameAction {
method EndTurnAction (line 8) | public EndTurnAction() {
method execute (line 13) | @Override
method getPromptText (line 18) | @Override
method isSameActionGroup (line 23) | @Override
method toString (line 28) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/GameAction.java
class GameAction (line 9) | public abstract class GameAction implements Cloneable {
method canBeExecutedOn (line 17) | public boolean canBeExecutedOn(GameContext gameContext, Player player,...
method clone (line 21) | @Override
method execute (line 31) | public abstract void execute(GameContext context, int playerId);
method getActionSuffix (line 33) | public String getActionSuffix() {
method getActionType (line 37) | public ActionType getActionType() {
method getPromptText (line 41) | public abstract String getPromptText();
method getSource (line 43) | public EntityReference getSource() {
method getTargetKey (line 47) | public EntityReference getTargetKey() {
method getTargetRequirement (line 51) | public TargetSelection getTargetRequirement() {
method isSameActionGroup (line 55) | public abstract boolean isSameActionGroup(GameAction anotherAction);
method setActionSuffix (line 57) | public void setActionSuffix(String actionSuffix) {
method setActionType (line 61) | protected void setActionType(ActionType actionType) {
method setSource (line 65) | public void setSource(EntityReference source) {
method setTarget (line 69) | public void setTarget(Entity target) {
method setTargetKey (line 73) | public void setTargetKey(EntityReference targetKey) {
method setTargetRequirement (line 77) | public void setTargetRequirement(TargetSelection targetRequirement) {
method toString (line 81) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/HeroPowerAction.java
class HeroPowerAction (line 8) | public class HeroPowerAction extends PlaySpellCardAction {
method HeroPowerAction (line 10) | public HeroPowerAction(SpellDesc spell, Card card, TargetSelection tar...
method execute (line 15) | @Override
method getPromptText (line 21) | @Override
method play (line 26) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/IActionSelectionListener.java
type IActionSelectionListener (line 3) | public interface IActionSelectionListener {
method onActionSelected (line 5) | void onActionSelected(GameAction action);
FILE: game/src/main/java/net/demilich/metastone/game/actions/IBattlecryCondition.java
type IBattlecryCondition (line 6) | public interface IBattlecryCondition {
method isFulfilled (line 8) | boolean isFulfilled(GameContext context, Player player);
FILE: game/src/main/java/net/demilich/metastone/game/actions/PhysicalAttackAction.java
class PhysicalAttackAction (line 12) | public class PhysicalAttackAction extends GameAction {
method PhysicalAttackAction (line 16) | public PhysicalAttackAction(EntityReference attackerReference) {
method canBeExecutedOn (line 22) | @Override
method execute (line 39) | @Override
method getAttackerReference (line 47) | public EntityReference getAttackerReference() {
method getPromptText (line 51) | @Override
method isSameActionGroup (line 56) | @Override
method toString (line 66) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/PlayCardAction.java
class PlayCardAction (line 14) | public abstract class PlayCardAction extends GameAction {
method PlayCardAction (line 21) | public PlayCardAction(CardReference cardReference) {
method canBeExecutedOn (line 25) | @Override
method execute (line 36) | @Override
method getCardReference (line 59) | public CardReference getCardReference() {
method getGroupIndex (line 63) | public int getGroupIndex() {
method getPromptText (line 67) | @Override
method isSameActionGroup (line 72) | @Override
method play (line 81) | protected abstract void play(GameContext context, int playerId);
method setGroupIndex (line 83) | public void setGroupIndex(int groupIndex) {
method toString (line 87) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/PlayChooseOneCardAction.java
class PlayChooseOneCardAction (line 9) | public class PlayChooseOneCardAction extends PlayCardAction {
method PlayChooseOneCardAction (line 15) | public PlayChooseOneCardAction(SpellDesc spell, Card chooseOneCard, St...
method play (line 24) | @Override
method getSpell (line 29) | public SpellDesc getSpell() {
method setSpell (line 33) | public void setSpell(SpellDesc spell) {
FILE: game/src/main/java/net/demilich/metastone/game/actions/PlayMinionCardAction.java
class PlayMinionCardAction (line 11) | public class PlayMinionCardAction extends PlayCardAction {
method PlayMinionCardAction (line 15) | public PlayMinionCardAction(CardReference cardReference) {
method PlayMinionCardAction (line 19) | public PlayMinionCardAction(CardReference cardReference, BattlecryActi...
method getPromptText (line 26) | @Override
method play (line 31) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/PlayPermanentCardAction.java
class PlayPermanentCardAction (line 11) | public class PlayPermanentCardAction extends PlayCardAction {
method PlayPermanentCardAction (line 15) | public PlayPermanentCardAction(CardReference cardReference) {
method PlayPermanentCardAction (line 19) | public PlayPermanentCardAction(CardReference cardReference, BattlecryA...
method getPromptText (line 26) | @Override
method play (line 31) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/actions/PlaySpellCardAction.java
class PlaySpellCardAction (line 9) | public class PlaySpellCardAction extends PlayCardAction {
method PlaySpellCardAction (line 14) | public PlaySpellCardAction(SpellDesc spell, Card card, TargetSelection...
method play (line 22) | @Override
method getSpell (line 27) | public SpellDesc getSpell() {
method setSpell (line 31) | public void setSpell(SpellDesc spell) {
FILE: game/src/main/java/net/demilich/metastone/game/actions/PlayWeaponCardAction.java
class PlayWeaponCardAction (line 7) | public class PlayWeaponCardAction extends PlayCardAction {
method PlayWeaponCardAction (line 9) | public PlayWeaponCardAction(CardReference cardReference) {
method play (line 14) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/Behaviour.java
class Behaviour (line 5) | public abstract class Behaviour implements IBehaviour {
method clone (line 7) | public IBehaviour clone() {
method onGameOver (line 16) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/DoNothingBehaviour.java
class DoNothingBehaviour (line 11) | public class DoNothingBehaviour extends Behaviour {
method getName (line 13) | @Override
method mulligan (line 18) | @Override
method requestAction (line 23) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/FlatMonteCarlo.java
class FlatMonteCarlo (line 15) | public class FlatMonteCarlo extends Behaviour {
method FlatMonteCarlo (line 21) | public FlatMonteCarlo(int iterations) {
method getBestAction (line 25) | private GameAction getBestAction(HashMap<GameAction, Double> actionSco...
method getName (line 39) | @Override
method mulligan (line 44) | @Override
method playRandomUntilEnd (line 55) | private int playRandomUntilEnd(GameContext simulation, int playerId) {
method requestAction (line 63) | @Override
method simulate (line 79) | private double simulate(GameContext context, int playerId, GameAction ...
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/GreedyOptimizeMove.java
class GreedyOptimizeMove (line 16) | public class GreedyOptimizeMove extends Behaviour {
method GreedyOptimizeMove (line 22) | public GreedyOptimizeMove(IGameStateHeuristic heuristic) {
method getName (line 26) | @Override
method mulligan (line 31) | @Override
method requestAction (line 42) | @Override
method simulateAction (line 67) | private GameContext simulateAction(GameContext simulation, Player play...
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/GreedyOptimizeTurn.java
class GreedyOptimizeTurn (line 17) | public class GreedyOptimizeTurn extends Behaviour {
method GreedyOptimizeTurn (line 27) | public GreedyOptimizeTurn(IGameStateHeuristic heuristic) {
method alphaBeta (line 31) | private double alphaBeta(GameContext context, int playerId, GameAction...
method clone (line 61) | @Override
method getName (line 75) | @Override
method mulligan (line 80) | @Override
method requestAction (line 91) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/IBehaviour.java
type IBehaviour (line 10) | public interface IBehaviour extends Cloneable {
method clone (line 12) | IBehaviour clone();
method getName (line 14) | String getName();
method mulligan (line 16) | List<Card> mulligan(GameContext context, Player player, List<Card> car...
method onGameOver (line 18) | void onGameOver(GameContext context, int playerId, int winningPlayerId);
method requestAction (line 20) | GameAction requestAction(GameContext context, Player player, List<Game...
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/NoAggressionBehaviour.java
class NoAggressionBehaviour (line 12) | public class NoAggressionBehaviour extends Behaviour {
method getName (line 14) | @Override
method mulligan (line 19) | @Override
method requestAction (line 24) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/PlayRandomBehaviour.java
class PlayRandomBehaviour (line 12) | public class PlayRandomBehaviour extends Behaviour {
method getName (line 16) | @Override
method mulligan (line 21) | @Override
method requestAction (line 26) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/TranspositionTable.java
class TranspositionTable (line 11) | public class TranspositionTable {
method hash (line 13) | private static int hash(Entity entity) {
method mergeHashes (line 25) | private static int mergeHashes(int hash1, int hash2) {
method clear (line 40) | public void clear() {
method getScore (line 44) | public double getScore(GameContext context) {
method hash (line 48) | private int hash(GameContext context) {
method known (line 77) | public boolean known(GameContext context) {
method save (line 87) | public void save(GameContext context, double score) {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/heuristic/IGameStateHeuristic.java
type IGameStateHeuristic (line 5) | public interface IGameStateHeuristic {
method getScore (line 7) | double getScore(GameContext context, int playerId);
method onActionSelected (line 9) | void onActionSelected(GameContext context, int playerId);
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/heuristic/WeightedFeature.java
type WeightedFeature (line 3) | public enum WeightedFeature {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/heuristic/WeightedHeuristic.java
class WeightedHeuristic (line 8) | public class WeightedHeuristic implements IGameStateHeuristic {
method calculateMinionScore (line 10) | private float calculateMinionScore(Minion minion) {
method getScore (line 41) | @Override
method onActionSelected (line 70) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/human/ActionGroup.java
class ActionGroup (line 8) | public class ActionGroup {
method ActionGroup (line 13) | public ActionGroup(GameAction prototype) {
method add (line 18) | public void add(GameAction action) {
method getActionsInGroup (line 22) | public List<GameAction> getActionsInGroup() {
method getPrototype (line 26) | public GameAction getPrototype() {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/human/HumanActionOptions.java
class HumanActionOptions (line 9) | public class HumanActionOptions {
method HumanActionOptions (line 16) | public HumanActionOptions(HumanBehaviour behaviour, GameContext contex...
method getBehaviour (line 23) | public HumanBehaviour getBehaviour() {
method getContext (line 27) | public GameContext getContext() {
method getPlayer (line 31) | public Player getPlayer() {
method getValidActions (line 35) | public List<GameAction> getValidActions() {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/human/HumanBehaviour.java
class HumanBehaviour (line 16) | public class HumanBehaviour extends Behaviour implements IActionSelectio...
method getName (line 22) | @Override
method mulligan (line 27) | @Override
method onActionSelected (line 44) | @Override
method requestAction (line 50) | @Override
method setMulliganCards (line 67) | public void setMulliganCards(List<Card> mulliganCards) {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/human/HumanMulliganOptions.java
class HumanMulliganOptions (line 8) | public class HumanMulliganOptions {
method HumanMulliganOptions (line 14) | public HumanMulliganOptions(Player player, HumanBehaviour behaviour, L...
method getBehaviour (line 20) | public HumanBehaviour getBehaviour() {
method getOfferedCards (line 24) | public List<Card> getOfferedCards() {
method getPlayer (line 28) | public Player getPlayer() {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/human/HumanTargetOptions.java
class HumanTargetOptions (line 6) | public class HumanTargetOptions {
method HumanTargetOptions (line 13) | public HumanTargetOptions(IActionSelectionListener actionSelectionList...
method getActionGroup (line 21) | public ActionGroup getActionGroup() {
method getActionSelectionListener (line 25) | public IActionSelectionListener getActionSelectionListener() {
method getContext (line 29) | public GameContext getContext() {
method getPlayerId (line 33) | public int getPlayerId() {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/learning/Brain.java
class Brain (line 13) | public class Brain implements IBrain {
method Brain (line 30) | public Brain() {
method backPropagation (line 36) | private void backPropagation(double[] in, double[] out, double[] expec...
method encodePlayer (line 64) | private void encodePlayer(Player player, double[] data, int offset) {
method gameStateToInput (line 82) | private double[] gameStateToInput(GameContext context, int playerId) {
method getEstimatedUtility (line 92) | @Override
method getOutput (line 97) | @Override
method gradient (line 103) | private double gradient(HiddenUnit hiddenUnit) {
method isLearning (line 107) | @Override
method learn (line 112) | @Override
method load (line 122) | public void load(String path) {
method save (line 144) | public void save(String path) {
method setLearning (line 153) | @Override
method wipeEligabilityTraces (line 158) | public void wipeEligabilityTraces() {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/learning/IBrain.java
type IBrain (line 5) | public interface IBrain {
method getEstimatedUtility (line 7) | public abstract double getEstimatedUtility(double[] output);
method getOutput (line 9) | public abstract double[] getOutput(GameContext context, int playerId);
method isLearning (line 11) | public abstract boolean isLearning();
method learn (line 13) | public abstract void learn(GameContext originalState, int playerId, do...
method load (line 15) | public abstract void load(String savePath);
method save (line 17) | public abstract void save(String savePath);
method setLearning (line 19) | public abstract void setLearning(boolean learning);
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/learning/LearningBehaviour.java
class LearningBehaviour (line 15) | public class LearningBehaviour extends Behaviour {
method LearningBehaviour (line 23) | public LearningBehaviour(boolean learn) {
method getName (line 28) | @Override
method mulligan (line 33) | @Override
method onGameOver (line 44) | @Override
method requestAction (line 61) | @Override
method save (line 95) | public void save() {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/mcts/ITreePolicy.java
type ITreePolicy (line 3) | interface ITreePolicy {
method select (line 5) | Node select(Node parent);
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/mcts/MonteCarloTreeSearch.java
class MonteCarloTreeSearch (line 13) | public class MonteCarloTreeSearch extends Behaviour {
method getName (line 19) | @Override
method mulligan (line 24) | @Override
method requestAction (line 35) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/mcts/Node.java
class Node (line 12) | class Node {
method Node (line 22) | public Node(GameAction incomingAction, int player) {
method canFurtherExpanded (line 27) | private boolean canFurtherExpanded() {
method expand (line 31) | private Node expand() {
method getBestAction (line 49) | public GameAction getBestAction() {
method getChildren (line 61) | public List<Node> getChildren() {
method getPlayer (line 65) | public int getPlayer() {
method getScore (line 69) | public int getScore() {
method getState (line 73) | public GameContext getState() {
method getVisits (line 77) | public int getVisits() {
method initState (line 81) | public void initState(GameContext state, List<GameAction> validActions) {
method isExpandable (line 86) | public boolean isExpandable() {
method isLeaf (line 96) | public boolean isLeaf() {
method isTerminal (line 100) | private boolean isTerminal() {
method process (line 104) | public void process(ITreePolicy treePolicy) {
method rollOut (line 125) | public int rollOut(Node node) {
method updateStats (line 141) | private void updateStats(int value) {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/mcts/UctPolicy.java
class UctPolicy (line 5) | class UctPolicy implements ITreePolicy {
method select (line 12) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/neutralnetwork/HiddenUnit.java
class HiddenUnit (line 5) | public class HiddenUnit implements Unit {
method HiddenUnit (line 28) | protected HiddenUnit(Unit[] units, double[] weights) {
method HiddenUnit (line 44) | protected HiddenUnit(Unit[] units, Random random) {
method getSum (line 54) | protected double getSum() {
method getValue (line 68) | public double getValue() {
method randomizeWeights (line 79) | public void randomizeWeights(Random random) {
method recompute (line 87) | public void recompute() {
method sigmoid (line 101) | protected double sigmoid(double x) {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/neutralnetwork/InputUnit.java
class InputUnit (line 3) | public class InputUnit implements Unit {
method InputUnit (line 21) | protected InputUnit() {
method getValue (line 29) | public double getValue() {
method recompute (line 36) | public void recompute() {
method setValue (line 44) | protected void setValue(double value) {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/neutralnetwork/NeuralNetwork.java
class NeuralNetwork (line 11) | public class NeuralNetwork implements Serializable {
method readFrom (line 25) | public static NeuralNetwork readFrom(String filename) throws IOExcepti...
method NeuralNetwork (line 52) | public NeuralNetwork(int input, int[] hidden) {
method NeuralNetwork (line 84) | public NeuralNetwork(NeuralNetwork net) {
method getValue (line 109) | public double[] getValue(double[] input) {
method writeTo (line 131) | public void writeTo(String filename) throws IOException {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/neutralnetwork/Unit.java
type Unit (line 5) | public interface Unit extends Serializable {
method getValue (line 12) | public double getValue();
method recompute (line 17) | public void recompute();
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/threat/GameStateValueBehaviour.java
class GameStateValueBehaviour (line 21) | public class GameStateValueBehaviour extends Behaviour {
method GameStateValueBehaviour (line 29) | public GameStateValueBehaviour() {
method GameStateValueBehaviour (line 32) | public GameStateValueBehaviour(FeatureVector featureVector, String nam...
method alphaBeta (line 38) | private double alphaBeta(GameContext context, int playerId, GameAction...
method answerTrainingData (line 59) | private void answerTrainingData(TrainingData trainingData) {
method clone (line 65) | @Override
method getName (line 73) | @Override
method mulligan (line 78) | @Override
method requestAction (line 90) | @Override
method requestTrainingData (line 120) | private void requestTrainingData(Player player) {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/threat/ThreatBasedHeuristic.java
class ThreatBasedHeuristic (line 15) | public class ThreatBasedHeuristic implements IGameStateHeuristic {
method calcuateThreatLevel (line 37) | private static ThreatLevel calcuateThreatLevel(GameContext context, in...
method getHeroDamage (line 56) | private static int getHeroDamage(Hero hero) {
method isHardRemoval (line 73) | private static boolean isHardRemoval(Card card) {
method ThreatBasedHeuristic (line 79) | public ThreatBasedHeuristic(FeatureVector vector) {
method calculateMinionScore (line 83) | private double calculateMinionScore(Minion minion, ThreatLevel threatL...
method getScore (line 129) | @Override
method onActionSelected (line 174) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/threat/ThreatLevel.java
type ThreatLevel (line 3) | enum ThreatLevel {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/threat/cuckoo/CuckooAgent.java
class CuckooAgent (line 5) | public class CuckooAgent implements Comparable<CuckooAgent> {
method CuckooAgent (line 10) | public CuckooAgent(FeatureVector data) {
method compareTo (line 14) | @Override
method getData (line 19) | public FeatureVector getData() {
method getFitness (line 23) | public double getFitness() {
method setData (line 27) | public void setData(FeatureVector data) {
method setFitness (line 31) | public void setFitness(double fitness) {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/threat/cuckoo/CuckooLearner.java
class CuckooLearner (line 14) | public class CuckooLearner {
method levyClamped (line 19) | private static double levyClamped(double base, double min, double max) {
method levyFlight (line 25) | private static FeatureVector levyFlight(FeatureVector base) {
method newRandomSolution (line 66) | private static CuckooAgent newRandomSolution() {
method CuckooLearner (line 77) | public CuckooLearner(Deck deckToTrain, List<Deck> decks) {
method evolve (line 87) | public void evolve() {
method getFittest (line 133) | public FeatureVector getFittest() {
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/threat/cuckoo/IFitnessFunction.java
type IFitnessFunction (line 5) | public interface IFitnessFunction {
method evaluate (line 7) | double evaluate(FeatureVector featureVector);
FILE: game/src/main/java/net/demilich/metastone/game/behaviour/threat/cuckoo/WinRateFitness.java
class WinRateFitness (line 24) | public class WinRateFitness implements IFitnessFunction {
class PlayGameTask (line 26) | private class PlayGameTask implements Callable<Void> {
method PlayGameTask (line 31) | public PlayGameTask(GameStatistics stats, FeatureVector solution) {
method call (line 36) | @Override
method WinRateFitness (line 67) | public WinRateFitness(Deck deckToTrain, List<Deck> decks) {
method evaluate (line 72) | @Override
method getRandomDeck (line 83) | private Deck getRandomDeck() {
method launchGames (line 87) | private double launchGames(FeatureVector solution, GameStatistics stat...
FILE: game/src/main/java/net/demilich/metastone/game/cards/Card.java
class Card (line 20) | public abstract class Card extends Entity {
method Card (line 34) | public Card(CardDesc desc) {
method clone (line 65) | @Override
method evaluateExpression (line 72) | public boolean evaluateExpression(String operator, int value1, int val...
method getBaseManaCost (line 90) | public int getBaseManaCost() {
method getBattlecry (line 94) | public BattlecryDesc getBattlecry() {
method getCardId (line 98) | public String getCardId() {
method getCardReference (line 102) | public CardReference getCardReference() {
method getCardSet (line 106) | public CardSet getCardSet() {
method getCardType (line 110) | public CardType getCardType() {
method getHeroClass (line 114) | public HeroClass getHeroClass() {
method getHeroClasses (line 118) | public HeroClass[] getHeroClasses() {
method getCopy (line 122) | public Card getCopy() {
method getDescription (line 132) | public String getDescription() {
method getEntityType (line 136) | @Override
method getLocation (line 141) | public CardLocation getLocation() {
method getManaCost (line 145) | public int getManaCost(GameContext context, Player player) {
method getRarity (line 153) | public Rarity getRarity() {
method getRace (line 157) | public Race getRace() {
method hasBattlecry (line 161) | public boolean hasBattlecry() {
method hasHeroClass (line 165) | public boolean hasHeroClass(HeroClass heroClass) {
method isCollectible (line 178) | public boolean isCollectible() {
method matchesFilter (line 182) | public boolean matchesFilter(String filter) {
method matchesSplitFilter (line 195) | public boolean matchesSplitFilter(String filter) {
method play (line 252) | public abstract PlayCardAction play();
method setBattlecry (line 254) | public void setBattlecry(BattlecryDesc battlecry) {
method setCollectible (line 258) | public void setCollectible(boolean collectible) {
method setDescription (line 262) | public void setDescription(String description) {
method setLocation (line 266) | public void setLocation(CardLocation location) {
method toString (line 270) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/CardCatalogue.java
class CardCatalogue (line 28) | public class CardCatalogue {
method add (line 39) | public static void add(Card card) {
method getAll (line 43) | public static CardCollection getAll() {
method getCardById (line 51) | public static Card getCardById(String id) {
method getCardByName (line 61) | public static Card getCardByName(String name) {
method getCardByBlizzardId (line 71) | public static Card getCardByBlizzardId(String id) throws IOException{
method getHeroes (line 83) | public static CardCollection getHeroes() {
method getHeroPowers (line 87) | public static CardCollection getHeroPowers(DeckFormat deckFormat) {
method query (line 91) | public static CardCollection query(DeckFormat deckFormat) {
method query (line 95) | public static CardCollection query(DeckFormat deckFormat, CardType car...
method query (line 99) | public static CardCollection query(DeckFormat deckFormat, HeroClass he...
method query (line 103) | public static CardCollection query(DeckFormat deckFormat, CardType car...
method query (line 107) | public static CardCollection query(DeckFormat deckFormat, CardType car...
method query (line 138) | public static CardCollection query(DeckFormat deckFormat, Predicate<Ca...
method loadLocalCards (line 151) | public static void loadLocalCards() throws IOException, URISyntaxExcep...
method loadCards (line 157) | public static void loadCards() throws IOException, URISyntaxException,...
method loadCards (line 164) | private static void loadCards(Collection<ResourceInputStream> inputStr...
method copyCardsFromResources (line 193) | public static void copyCardsFromResources() throws IOException, URISyn...
FILE: game/src/main/java/net/demilich/metastone/game/cards/CardCollection.java
class CardCollection (line 11) | public class CardCollection implements Iterable<Card>, Cloneable {
method CardCollection (line 15) | public CardCollection() {
method add (line 19) | public void add(Card card) {
method addAll (line 23) | public void addAll(CardCollection cardCollection) {
method addRandomly (line 29) | public void addRandomly(Card card) {
method clone (line 34) | public CardCollection clone() {
method contains (line 43) | public boolean contains(Card card) {
method containsCard (line 47) | public boolean containsCard(Card card) {
method get (line 59) | public Card get(int index) {
method getCount (line 63) | public int getCount() {
method getRandom (line 67) | public Card getRandom() {
method getRandomOfType (line 74) | public Card getRandomOfType(CardType cardType) {
method hasCardOfType (line 87) | public boolean hasCardOfType(CardType cardType) {
method isEmpty (line 96) | public boolean isEmpty() {
method iterator (line 100) | @Override
method peekFirst (line 105) | public Card peekFirst() {
method remove (line 109) | public boolean remove(Card card) {
method removeAll (line 113) | public void removeAll() {
method removeAll (line 117) | public void removeAll(Predicate<Card> filter) {
method removeFirst (line 121) | public Card removeFirst() {
method replace (line 125) | public boolean replace(Card oldCard, Card newCard) {
method shuffle (line 134) | public void shuffle() {
method sortByManaCost (line 138) | public void sortByManaCost() {
method sortByName (line 151) | public void sortByName() {
method toList (line 155) | public List<Card> toList() {
FILE: game/src/main/java/net/demilich/metastone/game/cards/CardDescType.java
type CardDescType (line 3) | public enum CardDescType {
FILE: game/src/main/java/net/demilich/metastone/game/cards/CardParseException.java
class CardParseException (line 6) | public class CardParseException extends Exception {
method CardParseException (line 14) | public CardParseException(List<String> badCards) {
method getMessage (line 18) | private static String getMessage(List<String> badCards) {
FILE: game/src/main/java/net/demilich/metastone/game/cards/CardParser.java
class CardParser (line 44) | public class CardParser {
method CardParser (line 50) | public CardParser() {
method parseCard (line 64) | public CardDesc parseCard(ResourceInputStream resourceInputStream) thr...
FILE: game/src/main/java/net/demilich/metastone/game/cards/CardSet.java
type CardSet (line 3) | public enum CardSet {
FILE: game/src/main/java/net/demilich/metastone/game/cards/CardType.java
type CardType (line 3) | public enum CardType {
method isCardType (line 12) | public boolean isCardType(CardType cardType) {
FILE: game/src/main/java/net/demilich/metastone/game/cards/ChooseBattlecryCard.java
class ChooseBattlecryCard (line 10) | public class ChooseBattlecryCard extends MinionCard implements IChooseOn...
method ChooseBattlecryCard (line 15) | public ChooseBattlecryCard(ChooseBattlecryCardDesc desc) {
method hasBothOptions (line 22) | public boolean hasBothOptions() {
method playOptions (line 26) | @Override
method playBothOptions (line 40) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/ChooseOneCard.java
class ChooseOneCard (line 8) | public class ChooseOneCard extends Card implements IChooseOneCard {
method ChooseOneCard (line 13) | public ChooseOneCard(ChooseOneCardDesc desc) {
method clone (line 20) | @Override
method getCard (line 28) | private Card getCard(String cardId) {
method getChoiceCards (line 36) | public Card[] getChoiceCards() {
method getBothChoicesCard (line 44) | public Card getBothChoicesCard() {
method hasBothOptions (line 48) | public boolean hasBothOptions() {
method play (line 52) | @Override
method playOptions (line 57) | @Override
method playBothOptions (line 71) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/HeroCard.java
class HeroCard (line 13) | public class HeroCard extends Card {
method HeroCard (line 20) | public HeroCard(HeroCardDesc desc) {
method createHero (line 26) | public Hero createHero() {
method play (line 38) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/IChooseOneCard.java
type IChooseOneCard (line 5) | public interface IChooseOneCard {
method playOptions (line 6) | PlayCardAction[] playOptions();
method playBothOptions (line 7) | PlayCardAction playBothOptions();
method hasBothOptions (line 8) | boolean hasBothOptions();
FILE: game/src/main/java/net/demilich/metastone/game/cards/MinionCard.java
class MinionCard (line 17) | public class MinionCard extends SummonCard {
method MinionCard (line 25) | public MinionCard(MinionCardDesc desc) {
method createMinion (line 38) | protected Minion createMinion(Attribute... tags) {
method getAttack (line 82) | public int getAttack() {
method getBonusAttack (line 86) | public int getBonusAttack() {
method getHp (line 90) | public int getHp() {
method getBonusHp (line 94) | public int getBonusHp() {
method getBaseAttack (line 98) | public int getBaseAttack() {
method getBaseHp (line 102) | public int getBaseHp() {
method play (line 106) | @Override
method setRace (line 111) | public void setRace(Race race) {
method summon (line 115) | public Minion summon() {
FILE: game/src/main/java/net/demilich/metastone/game/cards/PermanentCard.java
class PermanentCard (line 17) | public class PermanentCard extends SummonCard {
method PermanentCard (line 25) | public PermanentCard(PermanentCardDesc desc) {
method createPermanent (line 30) | protected Permanent createPermanent(Attribute... tags) {
method play (line 68) | @Override
method setRace (line 73) | public void setRace(Race race) {
method summon (line 77) | public Permanent summon() {
FILE: game/src/main/java/net/demilich/metastone/game/cards/QuestCard.java
class QuestCard (line 13) | public class QuestCard extends SpellCard {
method QuestCard (line 15) | public QuestCard(QuestCardDesc desc) {
method canBeCast (line 22) | public boolean canBeCast(GameContext context, Player player) {
method setQuest (line 26) | public void setQuest(Quest quest) {
FILE: game/src/main/java/net/demilich/metastone/game/cards/Rarity.java
type Rarity (line 3) | public enum Rarity {
method isRarity (line 10) | public boolean isRarity(Rarity rarity) {
FILE: game/src/main/java/net/demilich/metastone/game/cards/SecretCard.java
class SecretCard (line 13) | public class SecretCard extends SpellCard {
method SecretCard (line 15) | public SecretCard(SecretCardDesc desc) {
method canBeCast (line 22) | public boolean canBeCast(GameContext context, Player player) {
method setSecret (line 26) | public void setSecret(Secret secret) {
FILE: game/src/main/java/net/demilich/metastone/game/cards/SpellCard.java
class SpellCard (line 14) | public class SpellCard extends Card {
method SpellCard (line 20) | public SpellCard(SpellCardDesc desc) {
method canBeCast (line 29) | public boolean canBeCast(GameContext context, Player player) {
method canBeCastOn (line 47) | public boolean canBeCastOn(GameContext context, Player player, Entity ...
method clone (line 55) | @Override
method getSpell (line 66) | public SpellDesc getSpell() {
method getTargetRequirement (line 70) | public TargetSelection getTargetRequirement() {
method play (line 74) | @Override
method setSpell (line 79) | public void setSpell(SpellDesc spell) {
method setTargetRequirement (line 83) | public void setTargetRequirement(TargetSelection targetRequirement) {
FILE: game/src/main/java/net/demilich/metastone/game/cards/SummonCard.java
class SummonCard (line 7) | public abstract class SummonCard extends Card {
method SummonCard (line 9) | public SummonCard(SummonCardDesc desc) {
method play (line 13) | @Override
method summon (line 17) | public abstract Summon summon();
FILE: game/src/main/java/net/demilich/metastone/game/cards/WeaponCard.java
class WeaponCard (line 16) | public class WeaponCard extends Card {
method WeaponCard (line 24) | public WeaponCard(WeaponCardDesc desc) {
method createWeapon (line 34) | protected Weapon createWeapon(Attribute... tags) {
method getWeapon (line 77) | public Weapon getWeapon() {
method play (line 81) | @Override
method getDamage (line 86) | public int getDamage() {
method getBonusDamage (line 90) | public int getBonusDamage() {
method getDurability (line 94) | public int getDurability() {
method getBonusDurability (line 98) | public int getBonusDurability() {
method getBaseDamage (line 102) | public int getBaseDamage() {
method getBaseDurability (line 106) | public int getBaseDurability() {
FILE: game/src/main/java/net/demilich/metastone/game/cards/costmodifier/CardCostModifier.java
class CardCostModifier (line 24) | public class CardCostModifier extends CustomCloneable implements IGameEv...
method CardCostModifier (line 33) | public CardCostModifier(CardCostModifierDesc desc) {
method appliesTo (line 41) | public boolean appliesTo(Card card) {
method canFire (line 82) | @Override
method clone (line 87) | @Override
method expire (line 94) | public void expire() {
method get (line 98) | protected Object get(CardCostModifierArg arg) {
method getCardType (line 102) | protected CardType getCardType() {
method getHostReference (line 106) | @Override
method getMinValue (line 111) | public int getMinValue() {
method getOwner (line 115) | @Override
method getRequiredAttribute (line 120) | protected Attribute getRequiredAttribute() {
method getRequiredCardIds (line 124) | @SuppressWarnings("unchecked")
method getRequiredRace (line 132) | protected Race getRequiredRace() {
method getTargetPlayer (line 136) | protected TargetPlayer getTargetPlayer() {
method interestedIn (line 143) | @Override
method isExpired (line 151) | @Override
method onAdd (line 156) | @Override
method onGameEvent (line 160) | @Override
method onRemove (line 168) | @Override
method process (line 173) | public int process(Card card, int currentManaCost) {
method setHost (line 183) | @Override
method setOwner (line 188) | @Override
method hasPersistentOwner (line 196) | @Override
method oneTurnOnly (line 201) | @Override
method isDelayed (line 206) | @Override
method delayTimeDown (line 211) | @Override
method canFireCondition (line 216) | @Override
method hasCounter (line 224) | @Override
method countDown (line 229) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/costmodifier/OneTurnCostModifier.java
class OneTurnCostModifier (line 10) | public class OneTurnCostModifier extends CardCostModifier {
method OneTurnCostModifier (line 14) | public OneTurnCostModifier(CardCostModifierDesc desc) {
method clone (line 18) | @Override
method interestedIn (line 25) | @Override
method onGameEvent (line 34) | @Override
method oneTurnOnly (line 44) | @Override
method setOwner (line 49) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/costmodifier/ToggleCostModifier.java
class ToggleCostModifier (line 12) | public class ToggleCostModifier extends CardCostModifier {
method ToggleCostModifier (line 18) | public ToggleCostModifier(CardCostModifierDesc desc) {
method appliesTo (line 27) | @Override
method clone (line 35) | @Override
method interestedIn (line 43) | @Override
method onGameEvent (line 48) | @Override
method setOwner (line 58) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/ActorCardDesc.java
class ActorCardDesc (line 8) | public abstract class ActorCardDesc extends CardDesc {
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/AttributeDeserializer.java
class AttributeDeserializer (line 15) | public class AttributeDeserializer implements JsonDeserializer<Map<Attri...
method deserialize (line 17) | @Override
method parseAttribute (line 58) | private void parseAttribute(Attribute attribute, JsonObject jsonData, ...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/AuraDeserializer.java
class AuraDeserializer (line 16) | public class AuraDeserializer implements JsonDeserializer<AuraDesc> {
method deserialize (line 18) | @SuppressWarnings("unchecked")
method parseArgument (line 45) | private void parseArgument(AuraArg arg, JsonObject jsonData, Map<AuraA...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/CardCostModifierDeserializer.java
class CardCostModifierDeserializer (line 16) | public class CardCostModifierDeserializer implements JsonDeserializer<Ca...
method deserialize (line 18) | @SuppressWarnings("unchecked")
method parseArgument (line 49) | private void parseArgument(CardCostModifierArg arg, JsonObject jsonDat...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/CardDesc.java
class CardDesc (line 14) | public abstract class CardDesc {
method createInstance (line 32) | public abstract Card createInstance();
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/ChooseBattlecryCardDesc.java
class ChooseBattlecryCardDesc (line 7) | public class ChooseBattlecryCardDesc extends MinionCardDesc {
method createInstance (line 12) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/ChooseOneCardDesc.java
class ChooseOneCardDesc (line 6) | public class ChooseOneCardDesc extends CardDesc {
method createInstance (line 11) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/ConditionDeserializer.java
class ConditionDeserializer (line 16) | public class ConditionDeserializer implements JsonDeserializer<Condition...
method deserialize (line 18) | @SuppressWarnings("unchecked")
method parseArgument (line 53) | private void parseArgument(ConditionArg arg, JsonObject jsonData, Map<...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/Desc.java
class Desc (line 10) | public class Desc<T> {
method Desc (line 14) | public Desc(Map<T, Object> arguments) {
method contains (line 18) | public boolean contains(T arg) {
method get (line 22) | public Object get(T arg) {
method getBool (line 26) | public boolean getBool(T arg) {
method getInt (line 30) | public int getInt(T arg) {
method getString (line 34) | public String getString(T arg) {
method getValue (line 38) | public int getValue(T arg, GameContext context, Player player, Entity ...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/FilterDeserializer.java
class FilterDeserializer (line 16) | public class FilterDeserializer implements JsonDeserializer<FilterDesc> {
method deserialize (line 17) | @SuppressWarnings("unchecked")
method parseArgument (line 52) | private void parseArgument(FilterArg arg, JsonObject jsonData, Map<Fil...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/HeroCardDesc.java
class HeroCardDesc (line 7) | public class HeroCardDesc extends CardDesc {
method createInstance (line 12) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/HeroPowerCardDesc.java
class HeroPowerCardDesc (line 7) | public class HeroPowerCardDesc extends SpellCardDesc {
method createInstance (line 12) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/MinionCardDesc.java
class MinionCardDesc (line 7) | public class MinionCardDesc extends SummonCardDesc {
method createInstance (line 13) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/ParseUtils.java
class ParseUtils (line 36) | public class ParseUtils {
method parse (line 46) | public static Object parse(String argName, JsonObject jsonData, ParseV...
method parseEntityReference (line 173) | private static EntityReference parseEntityReference(String str) {
method toCamelCase (line 243) | public static String toCamelCase(String input) {
method tryParseBool (line 264) | public static boolean tryParseBool(String value) {
method tryParseInt (line 273) | public static boolean tryParseInt(String value) {
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/ParseValueType.java
type ParseValueType (line 3) | public enum ParseValueType {
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/PermanentCardDesc.java
class PermanentCardDesc (line 6) | public class PermanentCardDesc extends SummonCardDesc {
method createInstance (line 8) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/QuestCardDesc.java
class QuestCardDesc (line 7) | public class QuestCardDesc extends SpellCardDesc {
method createInstance (line 11) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/SecretCardDesc.java
class SecretCardDesc (line 7) | public class SecretCardDesc extends SpellCardDesc {
method createInstance (line 11) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/SourceDeserializer.java
class SourceDeserializer (line 16) | public class SourceDeserializer implements JsonDeserializer<SourceDesc> {
method deserialize (line 17) | @SuppressWarnings("unchecked")
method parseArgument (line 52) | private void parseArgument(SourceArg arg, JsonObject jsonData, Map<Sou...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/SpellCardDesc.java
class SpellCardDesc (line 9) | public class SpellCardDesc extends CardDesc {
method createInstance (line 15) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/SpellDeserializer.java
class SpellDeserializer (line 16) | public class SpellDeserializer implements JsonDeserializer<SpellDesc> {
method deserialize (line 18) | @SuppressWarnings("unchecked")
method parseArgument (line 83) | private void parseArgument(SpellArg spellArg, JsonObject jsonData, Map...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/SummonCardDesc.java
class SummonCardDesc (line 5) | public abstract class SummonCardDesc extends ActorCardDesc {
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/ValueProviderDeserializer.java
class ValueProviderDeserializer (line 16) | public class ValueProviderDeserializer implements JsonDeserializer<Value...
method deserialize (line 18) | @SuppressWarnings("unchecked")
method parseArgument (line 56) | private void parseArgument(ValueProviderArg arg, JsonObject jsonData, ...
FILE: game/src/main/java/net/demilich/metastone/game/cards/desc/WeaponCardDesc.java
class WeaponCardDesc (line 8) | public class WeaponCardDesc extends ActorCardDesc {
method createInstance (line 16) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/decks/Deck.java
class Deck (line 8) | public class Deck {
method Deck (line 17) | public Deck(HeroClass heroClass) {
method Deck (line 21) | public Deck(HeroClass heroClass, boolean arbitrary) {
method containsHowMany (line 26) | public int containsHowMany(Card card) {
method getCards (line 36) | public CardCollection getCards() {
method getCardsCopy (line 40) | public CardCollection getCardsCopy() {
method getDescription (line 44) | public String getDescription() {
method getHeroClass (line 48) | public HeroClass getHeroClass() {
method getName (line 52) | public String getName() {
method isArbitrary (line 56) | public boolean isArbitrary() {
method isComplete (line 60) | public boolean isComplete() {
method isFull (line 64) | public boolean isFull() {
method isMetaDeck (line 68) | public boolean isMetaDeck() {
method isTooBig (line 72) | public boolean isTooBig() {
method setDescription (line 76) | public void setDescription(String description) {
method setName (line 80) | public void setName(String name) {
method getFilename (line 84) | public String getFilename() {
method setFilename (line 88) | public void setFilename(String filename) {
FILE: game/src/main/java/net/demilich/metastone/game/decks/DeckFactory.java
class DeckFactory (line 9) | public class DeckFactory {
method getDeckConsistingof (line 11) | public static Deck getDeckConsistingof(int count, Card... cards) {
method getRandomDeck (line 23) | public static Deck getRandomDeck(HeroClass heroClass, DeckFormat deckF...
FILE: game/src/main/java/net/demilich/metastone/game/decks/DeckFormat.java
class DeckFormat (line 9) | public class DeckFormat {
method DeckFormat (line 15) | public DeckFormat() {
method addSet (line 19) | public void addSet(CardSet cardSet) {
method isInFormat (line 23) | public boolean isInFormat(Card card) {
method isInFormat (line 30) | public boolean isInFormat(CardSet set) {
method isInFormat (line 34) | public boolean isInFormat(Deck deck) {
method getCardSets (line 43) | public List<CardSet> getCardSets() {
method getName (line 47) | public String getName() {
method setName (line 51) | public void setName(String name) {
method getFilename (line 55) | public String getFilename() {
method setFilename (line 59) | public void setFilename(String filename) {
FILE: game/src/main/java/net/demilich/metastone/game/decks/MetaDeck.java
class MetaDeck (line 9) | public class MetaDeck extends Deck {
method MetaDeck (line 13) | public MetaDeck() {
method MetaDeck (line 17) | public MetaDeck(List<Deck> decks) {
method getDecks (line 22) | public List<Deck> getDecks() {
method isComplete (line 26) | public boolean isComplete() {
method selectRandom (line 30) | public Deck selectRandom() {
FILE: game/src/main/java/net/demilich/metastone/game/decks/RandomDeck.java
class RandomDeck (line 13) | public class RandomDeck extends Deck {
method RandomDeck (line 17) | public RandomDeck(HeroClass heroClass, DeckFormat deckFormat) {
method getCardsCopy (line 23) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/decks/validation/ArbitraryDeckValidator.java
class ArbitraryDeckValidator (line 7) | public class ArbitraryDeckValidator implements IDeckValidator {
method canAddCardToDeck (line 9) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/decks/validation/DefaultDeckValidator.java
class DefaultDeckValidator (line 8) | public class DefaultDeckValidator implements IDeckValidator {
method canAddCardToDeck (line 10) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/decks/validation/IDeckValidator.java
type IDeckValidator (line 6) | public interface IDeckValidator {
method canAddCardToDeck (line 8) | boolean canAddCardToDeck(Card card, Deck deck);
FILE: game/src/main/java/net/demilich/metastone/game/entities/Actor.java
class Actor (line 16) | public abstract class Actor extends Entity {
method Actor (line 22) | public Actor(Card sourceCard) {
method addDeathrattle (line 27) | public void addDeathrattle(SpellDesc deathrattleSpell) {
method addSpellTrigger (line 34) | public void addSpellTrigger(SpellTrigger spellTrigger) {
method canAttackThisTurn (line 38) | public boolean canAttackThisTurn() {
method clearSpellTriggers (line 51) | public void clearSpellTriggers() {
method clone (line 55) | @Override
method displayGameTag (line 73) | protected boolean displayGameTag(Attribute tag) {
method getAttack (line 80) | public int getAttack() {
method getBaseAttack (line 87) | public int getBaseAttack() {
method getBaseHp (line 91) | public int getBaseHp() {
method getBattlecry (line 95) | public BattlecryAction getBattlecry() {
method getCardCostModifier (line 99) | public CardCostModifier getCardCostModifier() {
method getDeathrattles (line 103) | @SuppressWarnings("unchecked")
method getHp (line 108) | public int getHp() {
method getMaxHp (line 112) | public int getMaxHp() {
method getRace (line 117) | public Race getRace() {
method getSourceCard (line 121) | public Card getSourceCard() {
method getSpellTriggers (line 125) | public List<SpellTrigger> getSpellTriggers() {
method hasSpellTrigger (line 129) | public boolean hasSpellTrigger() {
method getMaxNumberOfAttacks (line 133) | public int getMaxNumberOfAttacks() {
method isDestroyed (line 142) | @Override
method isWounded (line 147) | public boolean isWounded() {
method modifyAuraHpBonus (line 151) | public void modifyAuraHpBonus(int value) {
method modifyHpBonus (line 161) | @Override
method setAttack (line 173) | public void setAttack(int value) {
method setBaseAttack (line 177) | public void setBaseAttack(int value) {
method setBaseHp (line 181) | public void setBaseHp(int value) {
method setBattlecry (line 185) | public void setBattlecry(BattlecryAction battlecry) {
method setCardCostModifier (line 189) | public void setCardCostModifier(CardCostModifier cardCostModifier) {
method setHp (line 193) | public void setHp(int value) {
method setMaxHp (line 197) | public void setMaxHp(int value) {
method setOwner (line 201) | @Override
method setRace (line 209) | public void setRace(Race race) {
method toString (line 213) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/entities/Entity.java
class Entity (line 11) | public abstract class Entity extends CustomCloneable {
method clone (line 18) | @Override
method getAttribute (line 24) | public Object getAttribute(Attribute attribute) {
method getAttributes (line 28) | public Map<Attribute, Object> getAttributes() {
method getAttributeValue (line 32) | public int getAttributeValue(Attribute attribute) {
method getEntityType (line 36) | public abstract EntityType getEntityType();
method getId (line 38) | public int getId() {
method getName (line 42) | public String getName() {
method getOwner (line 46) | public int getOwner() {
method getReference (line 50) | public EntityReference getReference() {
method hasAttribute (line 54) | public boolean hasAttribute(Attribute attribute) {
method isDestroyed (line 65) | public boolean isDestroyed() {
method modifyAttribute (line 69) | public void modifyAttribute(Attribute attribute, int value) {
method modifyHpBonus (line 76) | public void modifyHpBonus(int value) {
method removeAttribute (line 80) | public void removeAttribute(Attribute attribute) {
method setAttribute (line 84) | public void setAttribute(Attribute attribute) {
method setAttribute (line 88) | public void setAttribute(Attribute attribute, int value) {
method setAttribute (line 92) | public void setAttribute(Attribute attribute, Object value) {
method setId (line 96) | public void setId(int id) {
method setName (line 100) | public void setName(String name) {
method setOwner (line 104) | public void setOwner(int ownerIndex) {
FILE: game/src/main/java/net/demilich/metastone/game/entities/EntityType.java
type EntityType (line 3) | public enum EntityType {
FILE: game/src/main/java/net/demilich/metastone/game/entities/heroes/Hero.java
class Hero (line 13) | public class Hero extends Actor {
method Hero (line 19) | public Hero(HeroCard heroCard, HeroPower heroPower) {
method activateWeapon (line 26) | public void activateWeapon(boolean active) {
method clone (line 32) | @Override
method getArmor (line 43) | public int getArmor() {
method getAttack (line 47) | @Override
method getAttributesCopy (line 56) | public Map<Attribute, Object> getAttributesCopy() {
method getEffectiveHp (line 64) | public int getEffectiveHp() {
method getEntityType (line 68) | @Override
method getHeroClass (line 73) | public HeroClass getHeroClass() {
method getHeroPower (line 77) | public HeroPower getHeroPower() {
method getWeapon (line 81) | public Weapon getWeapon() {
method modifyArmor (line 85) | public void modifyArmor(int armor) {
method setHeroClass (line 91) | public void setHeroClass(HeroClass heroClass) {
method setHeroPower (line 95) | public void setHeroPower(HeroPower heroPower) {
method setOwner (line 100) | @Override
method setWeapon (line 106) | public void setWeapon(Weapon weapon) {
FILE: game/src/main/java/net/demilich/metastone/game/entities/heroes/HeroClass.java
type HeroClass (line 3) | public enum HeroClass {
method isBaseClass (line 23) | public boolean isBaseClass() {
FILE: game/src/main/java/net/demilich/metastone/game/entities/heroes/MetaHero.java
class MetaHero (line 8) | public class MetaHero extends HeroCard {
method createDesc (line 10) | private static HeroCardDesc createDesc() {
method getHeroCard (line 20) | public static HeroCard getHeroCard(HeroClass heroClass) {
method MetaHero (line 46) | public MetaHero() {
FILE: game/src/main/java/net/demilich/metastone/game/entities/minions/Minion.java
class Minion (line 7) | public class Minion extends Summon {
method Minion (line 9) | public Minion(MinionCard sourceCard) {
method clone (line 15) | @Override
method getAttack (line 21) | @Override
method getEntityType (line 29) | @Override
method setBaseStats (line 34) | protected void setBaseStats(int baseAttack, int baseHp) {
FILE: game/src/main/java/net/demilich/metastone/game/entities/minions/Permanent.java
class Permanent (line 7) | public class Permanent extends Summon {
method Permanent (line 9) | public Permanent(PermanentCard sourceCard) {
method clone (line 14) | @Override
method getEntityType (line 20) | @Override
method isDestroyed (line 25) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/entities/minions/Race.java
type Race (line 3) | public enum Race {
FILE: game/src/main/java/net/demilich/metastone/game/entities/minions/RelativeToSource.java
type RelativeToSource (line 3) | public enum RelativeToSource {
FILE: game/src/main/java/net/demilich/metastone/game/entities/minions/Summon.java
class Summon (line 6) | public abstract class Summon extends Actor {
method Summon (line 8) | public Summon(Card sourceCard) {
method clone (line 12) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/entities/weapons/Weapon.java
class Weapon (line 12) | public class Weapon extends Actor {
method Weapon (line 18) | public Weapon(Card sourceCard) {
method clone (line 22) | @Override
method getBaseDurability (line 27) | public int getBaseDurability() {
method getDurability (line 31) | public int getDurability() {
method getEntityType (line 35) | @Override
method getMaxDurability (line 40) | public int getMaxDurability() {
method getWeaponDamage (line 44) | public int getWeaponDamage() {
method isActive (line 48) | public boolean isActive() {
method isBroken (line 52) | public boolean isBroken() {
method isDestroyed (line 56) | @Override
method onEquip (line 61) | public void onEquip(GameContext context, Player player) {
method onUnequip (line 67) | public void onUnequip(GameContext context, Player player) {
method setActive (line 73) | public void setActive(boolean active) {
method setOnEquip (line 77) | public void setOnEquip(SpellDesc onEquip) {
method setOnUnequip (line 81) | public void setOnUnequip(SpellDesc onUnequip) {
method toString (line 85) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/AfterPhysicalAttackEvent.java
class AfterPhysicalAttackEvent (line 7) | public class AfterPhysicalAttackEvent extends GameEvent {
method AfterPhysicalAttackEvent (line 13) | public AfterPhysicalAttackEvent(GameContext context, Actor attacker, A...
method getAttacker (line 20) | public Actor getAttacker() {
method getDamageDealt (line 24) | public int getDamageDealt() {
method getDefender (line 28) | public Actor getDefender() {
method getEventSource (line 32) | @Override
method getEventTarget (line 37) | @Override
method getEventType (line 42) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/AfterSpellCastedEvent.java
class AfterSpellCastedEvent (line 7) | public class AfterSpellCastedEvent extends GameEvent {
method AfterSpellCastedEvent (line 12) | public AfterSpellCastedEvent(GameContext context, int playerId, Card s...
method getEventSource (line 18) | @Override
method getEventTarget (line 23) | @Override
method getEventType (line 28) | @Override
method getSourceCard (line 33) | public Card getSourceCard() {
FILE: game/src/main/java/net/demilich/metastone/game/events/AfterSummonEvent.java
class AfterSummonEvent (line 8) | public class AfterSummonEvent extends GameEvent {
method AfterSummonEvent (line 13) | public AfterSummonEvent(GameContext context, Actor minion, Card source) {
method getEventTarget (line 19) | @Override
method getEventType (line 24) | @Override
method getMinion (line 29) | public Actor getMinion() {
method getSource (line 33) | public Card getSource() {
method toString (line 37) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/ArmorGainedEvent.java
class ArmorGainedEvent (line 7) | public class ArmorGainedEvent extends GameEvent {
method ArmorGainedEvent (line 11) | public ArmorGainedEvent(GameContext context, Hero hero) {
method getEventTarget (line 16) | @Override
method getEventType (line 21) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/BeforeSummonEvent.java
class BeforeSummonEvent (line 8) | public class BeforeSummonEvent extends GameEvent {
method BeforeSummonEvent (line 13) | public BeforeSummonEvent(GameContext context, Actor minion, Card sourc...
method getEventTarget (line 19) | @Override
method getEventType (line 24) | @Override
method getMinion (line 29) | public Actor getMinion() {
method getSource (line 33) | public Card getSource() {
method toString (line 37) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/BoardChangedEvent.java
class BoardChangedEvent (line 6) | public class BoardChangedEvent extends GameEvent {
method BoardChangedEvent (line 8) | public BoardChangedEvent(GameContext context) {
method getEventTarget (line 12) | @Override
method getEventType (line 17) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/CardPlayedEvent.java
class CardPlayedEvent (line 7) | public class CardPlayedEvent extends GameEvent {
method CardPlayedEvent (line 11) | public CardPlayedEvent(GameContext context, int playerId, Card card) {
method getCard (line 16) | public Card getCard() {
method getEventTarget (line 20) | @Override
method getEventType (line 25) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/CardRevealedEvent.java
class CardRevealedEvent (line 7) | public class CardRevealedEvent extends GameEvent {
method CardRevealedEvent (line 12) | public CardRevealedEvent(GameContext context, int playerId, Card card,...
method getCard (line 18) | public Card getCard() {
method getDelay (line 22) | public double getDelay() {
method getEventTarget (line 26) | @Override
method getEventType (line 31) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/DamageEvent.java
class DamageEvent (line 6) | public class DamageEvent extends GameEvent {
method DamageEvent (line 12) | public DamageEvent(GameContext context, Entity victim, Entity source, ...
method getDamage (line 19) | public int getDamage() {
method getEventSource (line 23) | @Override
method getEventTarget (line 28) | @Override
method getEventType (line 33) | @Override
method getSource (line 38) | public Entity getSource() {
method getVictim (line 42) | public Entity getVictim() {
FILE: game/src/main/java/net/demilich/metastone/game/events/DiscardEvent.java
class DiscardEvent (line 7) | public class DiscardEvent extends GameEvent {
method DiscardEvent (line 10) | public DiscardEvent(GameContext context, int playerId, Card card) {
method getCard (line 15) | public Card getCard() {
method getEventTarget (line 19) | @Override
method getEventType (line 24) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/DrawCardEvent.java
class DrawCardEvent (line 8) | public class DrawCardEvent extends GameEvent {
method DrawCardEvent (line 14) | public DrawCardEvent(GameContext context, int playerId, Card card, Car...
method getCard (line 21) | public Card getCard() {
method getEventTarget (line 25) | @Override
method getEventType (line 30) | @Override
method getSourceType (line 35) | public CardType getSourceType() {
method isDrawn (line 39) | public boolean isDrawn() {
FILE: game/src/main/java/net/demilich/metastone/game/events/EnrageChangedEvent.java
class EnrageChangedEvent (line 6) | public class EnrageChangedEvent extends GameEvent {
method EnrageChangedEvent (line 10) | public EnrageChangedEvent(GameContext context, Entity target) {
method getEventTarget (line 15) | @Override
method getEventType (line 20) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/GameEvent.java
class GameEvent (line 6) | public abstract class GameEvent {
method GameEvent (line 12) | public GameEvent(GameContext context, int targetPlayerId, int sourcePl...
method getEventTarget (line 25) | public abstract Entity getEventTarget();
method getEventSource (line 27) | public Entity getEventSource() {
method getEventType (line 31) | public abstract GameEventType getEventType();
method getGameContext (line 33) | public GameContext getGameContext() {
method getTargetPlayerId (line 37) | public int getTargetPlayerId() {
method getSourcePlayerId (line 41) | public int getSourcePlayerId() {
method toString (line 45) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/GameEventType.java
type GameEventType (line 3) | public enum GameEventType {
FILE: game/src/main/java/net/demilich/metastone/game/events/GameStartEvent.java
class GameStartEvent (line 6) | public class GameStartEvent extends GameEvent {
method GameStartEvent (line 9) | public GameStartEvent(GameContext context, int playerId) {
method getEventTarget (line 13) | @Override
method getEventType (line 18) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/HealEvent.java
class HealEvent (line 6) | public class HealEvent extends GameEvent {
method HealEvent (line 11) | public HealEvent(GameContext context, int playerId, Entity target, int...
method getEventTarget (line 17) | @Override
method getEventType (line 22) | @Override
method getHealing (line 27) | public int getHealing() {
method getTarget (line 31) | public Entity getTarget() {
FILE: game/src/main/java/net/demilich/metastone/game/events/HeroPowerUsedEvent.java
class HeroPowerUsedEvent (line 7) | public class HeroPowerUsedEvent extends GameEvent {
method HeroPowerUsedEvent (line 11) | public HeroPowerUsedEvent(GameContext context, int playerId, HeroPower...
method getEventTarget (line 16) | @Override
method getEventType (line 21) | @Override
method getHeroPower (line 26) | public HeroPower getHeroPower() {
FILE: game/src/main/java/net/demilich/metastone/game/events/JoustEvent.java
class JoustEvent (line 7) | public class JoustEvent extends GameEvent {
method JoustEvent (line 13) | public JoustEvent(GameContext context, int playerId, boolean won, Card...
method getEventTarget (line 20) | @Override
method getEventType (line 25) | @Override
method isWon (line 30) | public boolean isWon() {
method getOwnCard (line 34) | public Card getOwnCard() {
method getOpponentCard (line 38) | public Card getOpponentCard() {
FILE: game/src/main/java/net/demilich/metastone/game/events/KillEvent.java
class KillEvent (line 6) | public class KillEvent extends GameEvent {
method KillEvent (line 10) | public KillEvent(GameContext context, Entity victim) {
method getEventTarget (line 15) | @Override
method getEventType (line 20) | @Override
method getVictim (line 25) | public Entity getVictim() {
FILE: game/src/main/java/net/demilich/metastone/game/events/OverloadEvent.java
class OverloadEvent (line 7) | public class OverloadEvent extends GameEvent {
method OverloadEvent (line 11) | public OverloadEvent(GameContext context, int playerId, Card card) {
method getCard (line 16) | public Card getCard() {
method getEventTarget (line 20) | @Override
method getEventType (line 25) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/PhysicalAttackEvent.java
class PhysicalAttackEvent (line 7) | public class PhysicalAttackEvent extends GameEvent {
method PhysicalAttackEvent (line 13) | public PhysicalAttackEvent(GameContext context, Actor attacker, Actor ...
method getAttacker (line 20) | public Actor getAttacker() {
method getDamageDealt (line 24) | public int getDamageDealt() {
method getDefender (line 28) | public Actor getDefender() {
method getEventSource (line 32) | @Override
method getEventTarget (line 37) | @Override
method getEventType (line 42) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/PreDamageEvent.java
class PreDamageEvent (line 6) | public class PreDamageEvent extends GameEvent {
method PreDamageEvent (line 11) | public PreDamageEvent(GameContext context, Entity victim, Entity sourc...
method getEventTarget (line 17) | @Override
method getEventSource (line 22) | @Override
method getEventType (line 27) | @Override
method getSource (line 32) | public Entity getSource() {
method getVictim (line 36) | public Entity getVictim() {
FILE: game/src/main/java/net/demilich/metastone/game/events/QuestPlayedEvent.java
class QuestPlayedEvent (line 7) | public class QuestPlayedEvent extends GameEvent {
method QuestPlayedEvent (line 11) | public QuestPlayedEvent(GameContext context, int playerId, QuestCard q...
method getEventTarget (line 16) | @Override
method getEventType (line 21) | @Override
method getQuestCard (line 26) | public QuestCard getQuestCard() {
FILE: game/src/main/java/net/demilich/metastone/game/events/QuestSuccessfulEvent.java
class QuestSuccessfulEvent (line 7) | public class QuestSuccessfulEvent extends GameEvent {
method QuestSuccessfulEvent (line 11) | public QuestSuccessfulEvent(GameContext context, QuestCard quest, int ...
method getEventTarget (line 16) | @Override
method getEventType (line 21) | @Override
method getQuest (line 26) | public QuestCard getQuest() {
FILE: game/src/main/java/net/demilich/metastone/game/events/SecretPlayedEvent.java
class SecretPlayedEvent (line 7) | public class SecretPlayedEvent extends GameEvent {
method SecretPlayedEvent (line 11) | public SecretPlayedEvent(GameContext context, int playerId, SecretCard...
method getEventTarget (line 16) | @Override
method getEventType (line 21) | @Override
method getSecretCard (line 26) | public SecretCard getSecretCard() {
FILE: game/src/main/java/net/demilich/metastone/game/events/SecretRevealedEvent.java
class SecretRevealedEvent (line 7) | public class SecretRevealedEvent extends GameEvent {
method SecretRevealedEvent (line 11) | public SecretRevealedEvent(GameContext context, SecretCard secret, int...
method getEventTarget (line 16) | @Override
method getEventType (line 21) | @Override
method getSecret (line 26) | public SecretCard getSecret() {
FILE: game/src/main/java/net/demilich/metastone/game/events/SilenceEvent.java
class SilenceEvent (line 7) | public class SilenceEvent extends GameEvent {
method SilenceEvent (line 11) | public SilenceEvent(GameContext context, int playerId, Minion target) {
method getEventTarget (line 16) | @Override
method getEventType (line 21) | @Override
method getTarget (line 26) | public Minion getTarget() {
FILE: game/src/main/java/net/demilich/metastone/game/events/SpellCastedEvent.java
class SpellCastedEvent (line 7) | public class SpellCastedEvent extends GameEvent {
method SpellCastedEvent (line 11) | public SpellCastedEvent(GameContext context, int playerId, Card source...
method getEventSource (line 16) | @Override
method getEventTarget (line 21) | @Override
method getEventType (line 26) | @Override
method getSourceCard (line 31) | public Card getSourceCard() {
FILE: game/src/main/java/net/demilich/metastone/game/events/SummonEvent.java
class SummonEvent (line 8) | public class SummonEvent extends GameEvent {
method SummonEvent (line 13) | public SummonEvent(GameContext context, Actor minion, Card source) {
method getEventTarget (line 19) | @Override
method getEventType (line 24) | @Override
method getMinion (line 29) | public Actor getMinion() {
method getSource (line 33) | public Card getSource() {
method toString (line 37) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/TargetAcquisitionEvent.java
class TargetAcquisitionEvent (line 7) | public class TargetAcquisitionEvent extends GameEvent {
method TargetAcquisitionEvent (line 13) | public TargetAcquisitionEvent(GameContext context, int playerId, Actio...
method getActionType (line 20) | public ActionType getActionType() {
method getEventSource (line 24) | @Override
method getEventTarget (line 29) | @Override
method getEventType (line 34) | @Override
method getSource (line 39) | public Entity getSource() {
method getTarget (line 43) | public Entity getTarget() {
FILE: game/src/main/java/net/demilich/metastone/game/events/TurnEndEvent.java
class TurnEndEvent (line 6) | public class TurnEndEvent extends GameEvent {
method TurnEndEvent (line 8) | public TurnEndEvent(GameContext context, int playerId) {
method getEventTarget (line 12) | @Override
method getEventType (line 17) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/TurnStartEvent.java
class TurnStartEvent (line 6) | public class TurnStartEvent extends GameEvent {
method TurnStartEvent (line 9) | public TurnStartEvent(GameContext context, int playerId) {
method getEventTarget (line 13) | @Override
method getEventType (line 18) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/events/WeaponDestroyedEvent.java
class WeaponDestroyedEvent (line 7) | public class WeaponDestroyedEvent extends GameEvent {
method WeaponDestroyedEvent (line 11) | public WeaponDestroyedEvent(GameContext context, Weapon weapon) {
method getEventTarget (line 16) | @Override
method getEventType (line 21) | @Override
method getWeapon (line 26) | public Weapon getWeapon() {
FILE: game/src/main/java/net/demilich/metastone/game/events/WeaponEquippedEvent.java
class WeaponEquippedEvent (line 7) | public class WeaponEquippedEvent extends GameEvent {
method WeaponEquippedEvent (line 10) | public WeaponEquippedEvent(GameContext context, Weapon weapon) {
method getEventTarget (line 15) | @Override
method getEventType (line 20) | @Override
method getWeapon (line 25) | public Weapon getWeapon() {
FILE: game/src/main/java/net/demilich/metastone/game/gameconfig/GameConfig.java
class GameConfig (line 5) | public class GameConfig {
method getDeckFormat (line 12) | public DeckFormat getDeckFormat() {
method getNumberOfGames (line 16) | public int getNumberOfGames() {
method getPlayerConfig1 (line 20) | public PlayerConfig getPlayerConfig1() {
method getPlayerConfig2 (line 24) | public PlayerConfig getPlayerConfig2() {
method setDeckFormat (line 28) | public void setDeckFormat(DeckFormat deckFormat) {
method setNumberOfGames (line 32) | public void setNumberOfGames(int numberOfGames) {
method setPlayerConfig1 (line 36) | public void setPlayerConfig1(PlayerConfig playerConfig1) {
method setPlayerConfig2 (line 40) | public void setPlayerConfig2(PlayerConfig playerConfig2) {
FILE: game/src/main/java/net/demilich/metastone/game/gameconfig/PlayerConfig.java
class PlayerConfig (line 9) | public class PlayerConfig {
method PlayerConfig (line 20) | public PlayerConfig() {
method PlayerConfig (line 23) | public PlayerConfig(Deck deck, IBehaviour behaviour) {
method build (line 28) | public void build() {
method getBehaviour (line 40) | public IBehaviour getBehaviour() {
method getDeck (line 44) | public Deck getDeck() {
method getDeckForPlay (line 48) | public Deck getDeckForPlay() {
method getHeroCard (line 52) | public HeroCard getHeroCard() {
method getHeroForPlay (line 56) | public HeroCard getHeroForPlay() {
method getName (line 60) | public String getName() {
method hideCards (line 64) | public boolean hideCards() {
method setBehaviour (line 68) | public void setBehaviour(IBehaviour behaviour) {
method setDeck (line 72) | public void setDeck(Deck deck) {
method setHeroCard (line 76) | public void setHeroCard(HeroCard HeroCard) {
method setHideCards (line 80) | public void setHideCards(boolean hideCards) {
method setName (line 84) | public void setName(String name) {
FILE: game/src/main/java/net/demilich/metastone/game/heroes/powers/HeroPower.java
class HeroPower (line 11) | public class HeroPower extends SpellCard {
method HeroPower (line 15) | public HeroPower(HeroPowerCardDesc desc) {
method hasBeenUsed (line 20) | public int hasBeenUsed() {
method markUsed (line 24) | public void markUsed() {
method onWillUse (line 28) | public void onWillUse(GameContext context, Player player) {
method play (line 32) | @Override
method setUsed (line 37) | public void setUsed(int used) {
FILE: game/src/main/java/net/demilich/metastone/game/heroes/powers/HeroPowerChooseOne.java
class HeroPowerChooseOne (line 12) | public class HeroPowerChooseOne extends HeroPower implements IChooseOneC...
method HeroPowerChooseOne (line 17) | public HeroPowerChooseOne(HeroPowerCardDesc desc) {
method getCard (line 25) | private SpellCard getCard(String cardId) {
method hasBothOptions (line 33) | public boolean hasBothOptions() {
method play (line 37) | @Override
method playOptions (line 42) | @Override
method playBothOptions (line 57) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/logic/ActionLogic.java
class ActionLogic (line 24) | public class ActionLogic {
method getAutoHeroPower (line 28) | public GameAction getAutoHeroPower(GameContext context, Player player) {
method getHeroAttackActions (line 32) | private List<GameAction> getHeroAttackActions(GameContext context, Pla...
method getHeroPowerActions (line 43) | private List<GameAction> getHeroPowerActions(GameContext context, Play...
method getPhysicalAttackActions (line 64) | private List<GameAction> getPhysicalAttackActions(GameContext context,...
method getPlayCardActions (line 78) | private List<GameAction> getPlayCardActions(GameContext context, Playe...
method getValidActions (line 106) | public List<GameAction> getValidActions(GameContext context, Player pl...
method hasAutoHeroPower (line 117) | public boolean hasAutoHeroPower(GameContext context, Player player) {
method rollout (line 125) | public void rollout(GameAction action, GameContext context, Player pla...
FILE: game/src/main/java/net/demilich/metastone/game/logic/CustomCloneable.java
class CustomCloneable (line 3) | public class CustomCloneable implements Cloneable {
method clone (line 5) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/logic/GameLogic.java
class GameLogic (line 93) | public class GameLogic implements Cloneable {
method hasPlayerLost (line 116) | private static boolean hasPlayerLost(Player player) {
method GameLogic (line 133) | public GameLogic() {
method GameLogic (line 137) | private GameLogic(IdFactory idFactory) {
method addGameEventListener (line 141) | public void addGameEventListener(Player player, IGameEventListener gam...
method addManaModifier (line 153) | public void addManaModifier(Player player, CardCostModifier cardCostMo...
method afterCardPlayed (line 158) | public void afterCardPlayed(int playerId, CardReference cardReference) {
method applyAmplify (line 167) | public int applyAmplify(Player player, int baseValue, Attribute attrib...
method applyAttribute (line 172) | public void applyAttribute(Entity entity, Attribute attr) {
method applyHeroPowerDamage (line 194) | public int applyHeroPowerDamage(Player player, int baseValue) {
method applySpellpower (line 210) | public int applySpellpower(Player player, Entity source, int baseValue) {
method assignCardIds (line 224) | private void assignCardIds(CardCollection cardCollection) {
method attributeExists (line 231) | public boolean attributeExists(Attribute attr) {
method canPlayCard (line 246) | public boolean canPlayCard(int playerId, CardReference cardReference) {
method canPlayQuest (line 286) | public boolean canPlayQuest(Player player, QuestCard card) {
method canPlaySecret (line 290) | public boolean canPlaySecret(Player player, SecretCard card) {
method canSummonMoreMinions (line 294) | public boolean canSummonMoreMinions(Player player) {
method castChooseOneSpell (line 298) | public void castChooseOneSpell(int playerId, SpellDesc spellDesc, Enti...
method castSpell (line 353) | public void castSpell(int playerId, SpellDesc spellDesc, EntityReferen...
method castSpell (line 358) | public void castSpell(int playerId, SpellDesc spellDesc, EntityReferen...
method changeHero (line 422) | public void changeHero(Player player, Hero hero) {
method checkForDeadEntities (line 435) | public void checkForDeadEntities() {
method checkForDeadEntities (line 443) | public void checkForDeadEntities(int i) {
method clone (line 482) | @Override
method damage (line 489) | public int damage(Player player, Actor target, int baseDamage, Entity ...
method damage (line 493) | public int damage(Player player, Actor target, int baseDamage, Entity ...
method damageHero (line 542) | private int damageHero(Hero hero, int damage) {
method damageMinion (line 555) | private int damageMinion(Actor minion, int damage) {
method destroy (line 575) | public void destroy(Actor... targets) {
method destroyMinion (line 626) | private void destroyMinion(Minion minion) {
method destroyWeapon (line 636) | private void destroyWeapon(Weapon weapon) {
method determineBeginner (line 646) | public int determineBeginner(int... playerIds) {
method discardCard (line 650) | public void discardCard(Player player, Card card) {
method drawCard (line 660) | public Card drawCard(int playerId, Entity source) {
method drawCard (line 678) | public Card drawCard(int playerId, Card card, Entity source) {
method drawSetAsideCard (line 686) | public void drawSetAsideCard(int playerId, Card card) {
method endTurn (line 695) | public void endTurn(int playerId) {
method equipWeapon (line 719) | public void equipWeapon(int playerId, Weapon weapon) {
method equipWeapon (line 723) | public void equipWeapon(int playerId, Weapon weapon, boolean battlecry) {
method fight (line 762) | public void fight(Player player, Actor attacker, Actor defender) {
method gainArmor (line 828) | public void gainArmor(Player player, int armor) {
method generateCardID (line 837) | public String generateCardID() {
method getAnotherRandomTarget (line 841) | public Actor getAnotherRandomTarget(Player player, Actor attacker, Act...
method getAttributeValue (line 866) | public int getAttributeValue(Player player, Attribute attr, int defaul...
method getAutoHeroPowerAction (line 876) | public GameAction getAutoHeroPowerAction(int playerId) {
method getGreatestAttributeValue (line 891) | public int getGreatestAttributeValue(Player player, Attribute attr) {
method getMatchResult (line 909) | public MatchResult getMatchResult(Player player, Player opponent) {
method getModifiedManaCost (line 920) | public int getModifiedManaCost(Player player, Card card) {
method getQuests (line 939) | public List<IGameEventListener> getQuests(Player player) {
method getSecrets (line 950) | public List<IGameEventListener> getSecrets(Player player) {
method getTotalAttributeValue (line 961) | public int getTotalAttributeValue(Attribute attr) {
method getTotalAttributeValue (line 969) | public int getTotalAttributeValue(Player player, Attribute attr) {
method getTotalAttributeMultiplier (line 981) | public int getTotalAttributeMultiplier(Player player, Attribute attrib...
method getValidActions (line 994) | public List<GameAction> getValidActions(int playerId) {
method getValidTargets (line 999) | public List<Entity> getValidTargets(int playerId, GameAction action) {
method getWinner (line 1004) | public Player getWinner(Player player, Player opponent) {
method handleEnrage (line 1017) | private void handleEnrage(Actor entity) {
method handleFrozen (line 1038) | private void handleFrozen(Actor actor) {
method hasAttribute (line 1047) | public boolean hasAttribute(Player player, Attribute attr) {
method hasAutoHeroPower (line 1060) | public boolean hasAutoHeroPower(int player) {
method hasCard (line 1064) | public boolean hasCard(Player player, Card card) {
method heal (line 1076) | public void heal(Player player, Actor target, int healing, Entity sour...
method healHero (line 1106) | private boolean healHero(Hero hero, int healing) {
method healMinion (line 1117) | private boolean healMinion(Actor minion, int healing) {
method init (line 1129) | public void init(int playerId, boolean begins) {
method isLoggingEnabled (line 1163) | public boolean isLoggingEnabled() {
method joust (line 1167) | public JoustEvent joust(Player player) {
method log (line 1196) | private void log(String message) {
method log (line 1203) | private void log(String message, Object param1) {
method log (line 1210) | private void log(String message, Object param1, Object param2) {
method log (line 1217) | private void log(String message, Object param1, Object param2, Object ...
method logToDebugHistory (line 1224) | private void logToDebugHistory(String message, Object... params) {
method markAsDestroyed (line 1239) | public void markAsDestroyed(Actor target) {
method mindControl (line 1245) | public void mindControl(Player player, Summon summon) {
method modifyCurrentMana (line 1270) | public void modifyCurrentMana(int playerId, int mana) {
method modifyDurability (line 1276) | public void modifyDurability(Weapon weapon, int durability) {
method modifyMaxHp (line 1285) | public void modifyMaxHp(Actor actor, int value) {
method modifyMaxMana (line 1291) | public void modifyMaxMana(Player player, int delta) {
method mulligan (line 1300) | private void mulligan(Player player, boolean begins) {
method panicDump (line 1346) | public void panicDump() {
method performGameAction (line 1353) | public void performGameAction(int playerId, GameAction action) {
method playCard (line 1375) | public void playCard(int playerId, CardReference cardReference) {
method playQuest (line 1419) | public void playQuest(Player player, Quest quest) {
method playQuest (line 1423) | public void playQuest(Player player, Quest quest, boolean fromHand) {
method playSecret (line 1433) | public void playSecret(Player player, Secret secret) {
method playSecret (line 1437) | public void playSecret(Player player, Secret secret, boolean fromHand) {
method processTargetModifiers (line 1446) | public void processTargetModifiers(Player player, GameAction action) {
method random (line 1465) | public int random(int max) {
method randomBool (line 1469) | public boolean randomBool() {
method receiveCard (line 1473) | public void receiveCard(int playerId, Card card) {
method receiveCard (line 1477) | public void receiveCard(int playerId, Card card, Entity source) {
method receiveCard (line 1481) | public void receiveCard(int playerId, Card card, Entity source, boolea...
method refreshAttacksPerRound (line 1511) | public void refreshAttacksPerRound(Entity entity) {
method removeAttribute (line 1521) | public void removeAttribute(Entity entity, Attribute attr) {
method removeCard (line 1537) | public void removeCard(int playerId, Card card) {
method removeAllCards (line 1546) | public void removeAllCards(int playerId) {
method removeCardFromDeck (line 1552) | public void removeCardFromDeck(int playerID, Card card) {
method removeQuests (line 1561) | public void removeQuests(Player player) {
method removeSummon (line 1572) | public void removeSummon(Summon summon, boolean peacefully) {
method removeSecrets (line 1589) | public void removeSecrets(Player player) {
method removeSpellTriggers (line 1601) | private void removeSpellTriggers(Entity entity) {
method removeSpellTriggers (line 1605) | private void removeSpellTriggers(Entity entity, boolean removeAuras) {
method replaceCard (line 1623) | public void replaceCard(int playerId, Card oldCard, Card newCard) {
method replaceCardInDeck (line 1648) | public void replaceCardInDeck(int playerId, Card oldCard, Card newCard) {
method resolveBattlecry (line 1672) | private void resolveBattlecry(int playerId, Actor actor) {
method resolveDeathrattles (line 1714) | public void resolveDeathrattles(Player player, Actor actor) {
method resolveDeathrattles (line 1718) | public void resolveDeathrattles(Player player, Actor actor, int boardP...
method questTriggered (line 1736) | public void questTriggered(Player player, Quest quest) {
method secretTriggered (line 1743) | public void secretTriggered(Player player, Secret secret) {
method setContext (line 1750) | public void setContext(GameContext context) {
method setLoggingEnabled (line 1754) | public void setLoggingEnabled(boolean loggingEnabled) {
method shuffleToDeck (line 1758) | public void shuffleToDeck(Player player, Card card) {
method silence (line 1775) | public void silence(int playerId, Minion target) {
method startTurn (line 1811) | public void startTurn(int playerId) {
method summon (line 1844) | public boolean summon(int playerId, Summon summon) {
method summon (line 1848) | public boolean summon(int playerId, Summon summon, Card source, int in...
method transformMinion (line 1946) | public void transformMinion(Summon summon, Summon newSummon) {
method useHeroPower (line 2016) | public void useHeroPower(int playerId) {
FILE: game/src/main/java/net/demilich/metastone/game/logic/MatchResult.java
type MatchResult (line 3) | public enum MatchResult {
FILE: game/src/main/java/net/demilich/metastone/game/logic/TargetLogic.java
class TargetLogic (line 24) | public class TargetLogic {
method singleTargetAsList (line 28) | private static List<Entity> singleTargetAsList(Entity target) {
method containsTaunters (line 34) | private boolean containsTaunters(List<Minion> minions) {
method filterTargets (line 43) | private List<Entity> filterTargets(GameContext context, Player player,...
method findEntity (line 72) | public Entity findEntity(GameContext context, EntityReference targetKe...
method findInCards (line 120) | private Entity findInCards(Player player, int targetId) {
method findInEnvironment (line 138) | private Entity findInEnvironment(GameContext context, EntityReference ...
method getEntities (line 145) | private List<Entity> getEntities(GameContext context, Player player, T...
method getTaunters (line 174) | private List<Entity> getTaunters(List<Minion> entities) {
method getValidTargets (line 184) | public List<Entity> getValidTargets(GameContext context, Player player...
method resolveTargetKey (line 209) | public List<Entity> resolveTargetKey(GameContext context, Player playe...
FILE: game/src/main/java/net/demilich/metastone/game/spells/AddAttributeSpell.java
class AddAttributeSpell (line 14) | public class AddAttributeSpell extends RevertableSpell {
method create (line 16) | public static SpellDesc create(Attribute tag) {
method create (line 20) | public static SpellDesc create(Attribute tag, GameEventTrigger revertT...
method create (line 24) | public static SpellDesc create(EntityReference target, Attribute tag) {
method create (line 28) | public static SpellDesc create(EntityReference target, Attribute tag, ...
method getReverseSpell (line 36) | @Override
method onCast (line 41) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/AddDeathrattleSpell.java
class AddDeathrattleSpell (line 13) | public class AddDeathrattleSpell extends Spell {
method create (line 15) | public static SpellDesc create(EntityReference target, SpellDesc death...
method create (line 22) | public static SpellDesc create(SpellDesc deathrattle) {
method onCast (line 26) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/AddQuestSpell.java
class AddQuestSpell (line 13) | public class AddQuestSpell extends Spell {
method create (line 15) | public static SpellDesc create(Quest quest) {
method create (line 19) | public static SpellDesc create(EntityReference target, Quest quest) {
method onCast (line 26) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/AddSecretSpell.java
class AddSecretSpell (line 13) | public class AddSecretSpell extends Spell {
method create (line 15) | public static SpellDesc create(Secret secret) {
method create (line 19) | public static SpellDesc create(EntityReference target, Secret secret) {
method onCast (line 26) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/AddSpellTriggerSpell.java
class AddSpellTriggerSpell (line 14) | public class AddSpellTriggerSpell extends Spell {
method create (line 16) | public static SpellDesc create(EntityReference target, TriggerDesc tri...
method create (line 23) | public static SpellDesc create(TriggerDesc trigger) {
method onCast (line 27) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/AdjacentEffectSpell.java
class AdjacentEffectSpell (line 14) | public class AdjacentEffectSpell extends Spell {
method create (line 16) | public static SpellDesc create(EntityReference target, SpellDesc prima...
method create (line 31) | public static SpellDesc create(SpellDesc primarySpell, SpellDesc secon...
method onCast (line 35) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/AuraBuffSpell.java
class AuraBuffSpell (line 17) | public class AuraBuffSpell extends Spell {
method create (line 21) | public static SpellDesc create(int attackBonus) {
method create (line 25) | public static SpellDesc create(int attackBonus, int hpBonus) {
method create (line 29) | public static SpellDesc create(int attackBonus, int hpBonus, Predicate...
method onCast (line 40) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/BuffHeroSpell.java
class BuffHeroSpell (line 17) | public class BuffHeroSpell extends Spell {
method create (line 21) | public static SpellDesc create(int attackBonus, int armorBonus) {
method create (line 25) | public static SpellDesc create(EntityReference target, int attackBonus...
method onCast (line 33) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/BuffSpell.java
class BuffSpell (line 16) | public class BuffSpell extends Spell {
method create (line 20) | public static SpellDesc create(EntityReference target, int value) {
method create (line 27) | public static SpellDesc create(EntityReference target, int attackBonus...
method onCast (line 35) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/BuffWeaponSpell.java
class BuffWeaponSpell (line 17) | public class BuffWeaponSpell extends Spell {
method create (line 21) | public static SpellDesc create(int attackBonus, int durabilityBonus) {
method create (line 25) | public static SpellDesc create(EntityReference target, int attackBonus...
method onCast (line 33) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CardCostModifierSpell.java
class CardCostModifierSpell (line 20) | public class CardCostModifierSpell extends Spell {
method create (line 22) | public static SpellDesc create(CardCostModifierDesc cardCostModifierDe...
method create (line 26) | public static SpellDesc create(CardCostModifierDesc cardCostModifierDe...
method create (line 33) | public static SpellDesc create(EntityReference target, AlgebraicOperat...
method create (line 38) | public static SpellDesc create(EntityReference target, AlgebraicOperat...
method onCast (line 46) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CastRandomSpellSpell.java
class CastRandomSpellSpell (line 30) | public class CastRandomSpellSpell extends Spell {
method create (line 34) | public static SpellDesc create(int value) {
method onCast (line 40) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CastRepeatedlySpell.java
class CastRepeatedlySpell (line 13) | public class CastRepeatedlySpell extends Spell {
method create (line 15) | public static SpellDesc create(SpellDesc spell, int value) {
method onCast (line 22) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/ChangeHeroPowerSpell.java
class ChangeHeroPowerSpell (line 14) | public class ChangeHeroPowerSpell extends Spell {
method changeHeroPower (line 18) | protected void changeHeroPower(GameContext context, String newHeroPowe...
method onCast (line 24) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/ChangeHeroSpell.java
class ChangeHeroSpell (line 12) | public class ChangeHeroSpell extends Spell {
method create (line 14) | public static SpellDesc create(String heroCardId) {
method onCast (line 20) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/ClearOverloadSpell.java
class ClearOverloadSpell (line 12) | public class ClearOverloadSpell extends Spell {
method create (line 14) | public static SpellDesc create() {
method onCast (line 19) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CloneMinionSpell.java
class CloneMinionSpell (line 11) | public class CloneMinionSpell extends Spell {
method onCast (line 13) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/ComboSpell.java
class ComboSpell (line 12) | public class ComboSpell extends ConditionalEffectSpell {
method create (line 14) | public static SpellDesc create(SpellDesc either, SpellDesc or, boolean...
method isConditionFulfilled (line 22) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/ConditionalAttackBonusSpell.java
class ConditionalAttackBonusSpell (line 14) | public class ConditionalAttackBonusSpell extends Spell {
method create (line 16) | public static SpellDesc create(EntityReference target, ValueProvider v...
method create (line 23) | public static SpellDesc create(ValueProvider valueProvider) {
method onCast (line 27) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/ConditionalEffectSpell.java
class ConditionalEffectSpell (line 10) | public class ConditionalEffectSpell extends Spell {
method isConditionFulfilled (line 12) | protected boolean isConditionFulfilled(GameContext context, Player pla...
method onCast (line 17) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/ConditionalSpell.java
class ConditionalSpell (line 10) | public class ConditionalSpell extends Spell {
method onCast (line 12) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CopyCardSpell.java
class CopyCardSpell (line 17) | public class CopyCardSpell extends Spell {
method onCast (line 21) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CopyDeathrattleSpell.java
class CopyDeathrattleSpell (line 13) | public class CopyDeathrattleSpell extends Spell {
method create (line 15) | public static SpellDesc create(EntityReference target) {
method onCast (line 21) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CopyHeroPower.java
class CopyHeroPower (line 8) | public class CopyHeroPower extends ChangeHeroPowerSpell {
method onCast (line 10) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CreateCardSpell.java
class CreateCardSpell (line 27) | public class CreateCardSpell extends Spell {
method discoverCardParts (line 31) | private SpellDesc[] discoverCardParts(GameContext context, Player play...
method onCast (line 76) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/CreateSummonSpell.java
class CreateSummonSpell (line 20) | public class CreateSummonSpell extends Spell {
method onCast (line 24) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DamageSpell.java
class DamageSpell (line 15) | public class DamageSpell extends Spell {
method create (line 17) | public static SpellDesc create(EntityReference target, int damage) {
method create (line 21) | public static SpellDesc create(EntityReference target, int damage, boo...
method create (line 25) | public static SpellDesc create(EntityReference target, int damage, Pre...
method create (line 36) | public static SpellDesc create(EntityReference target, ValueProvider d...
method create (line 43) | public static SpellDesc create(int damage) {
method create (line 47) | public static SpellDesc create(ValueProvider damageModfier) {
method onCast (line 51) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DestroyAllExceptOneSpell.java
class DestroyAllExceptOneSpell (line 15) | public class DestroyAllExceptOneSpell extends DestroySpell {
method cast (line 19) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DestroySecretsSpell.java
class DestroySecretsSpell (line 12) | public class DestroySecretsSpell extends Spell {
method create (line 14) | public static SpellDesc create(TargetPlayer targetPlayer) {
method onCast (line 21) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DestroySpell.java
class DestroySpell (line 14) | public class DestroySpell extends Spell {
method create (line 16) | public static SpellDesc create() {
method create (line 20) | public static SpellDesc create(EntityReference target) {
method create (line 24) | public static SpellDesc create(EntityReference target, boolean randomT...
method create (line 28) | public static SpellDesc create(EntityReference target, Predicate<Entit...
method onCast (line 38) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DiscardCardsFromDeckSpell.java
class DiscardCardsFromDeckSpell (line 13) | public class DiscardCardsFromDeckSpell extends Spell {
method create (line 15) | public static SpellDesc create(int howMany) {
method onCast (line 22) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DiscardSpell.java
class DiscardSpell (line 15) | public class DiscardSpell extends Spell {
method create (line 19) | public static SpellDesc create() {
method create (line 23) | public static SpellDesc create(int numberOfCards) {
method onCast (line 30) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DiscoverCardSpell.java
class DiscoverCardSpell (line 14) | public class DiscoverCardSpell extends Spell {
method create (line 16) | public static SpellDesc create(EntityReference target, SpellDesc spell) {
method onCast (line 23) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DiscoverDrawSpell.java
class DiscoverDrawSpell (line 11) | public class DiscoverDrawSpell extends Spell {
method onCast (line 13) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DiscoverFilteredCardSpell.java
class DiscoverFilteredCardSpell (line 17) | public class DiscoverFilteredCardSpell extends Spell {
method create (line 19) | public static SpellDesc create(EntityReference target, SpellDesc spell) {
method onCast (line 26) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DiscoverOptionSpell.java
class DiscoverOptionSpell (line 19) | public class DiscoverOptionSpell extends Spell {
method create (line 23) | public static SpellDesc create(EntityReference target, SpellDesc spell) {
method onCast (line 30) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DiscoverRandomCardSpell.java
class DiscoverRandomCardSpell (line 18) | public class DiscoverRandomCardSpell extends Spell {
method create (line 20) | public static SpellDesc create(EntityReference target, SpellDesc spell) {
method onCast (line 27) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DoubleAttackSpell.java
class DoubleAttackSpell (line 14) | public class DoubleAttackSpell extends Spell {
method create (line 16) | public static SpellDesc create() {
method create (line 20) | public static SpellDesc create(EntityReference target) {
method onCast (line 26) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DrawCardAndDoSomethingSpell.java
class DrawCardAndDoSomethingSpell (line 11) | public class DrawCardAndDoSomethingSpell extends Spell {
method onCast (line 13) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DrawCardSpell.java
class DrawCardSpell (line 9) | public class DrawCardSpell extends Spell {
method onCast (line 11) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/DrawCardUntilConditionSpell.java
class DrawCardUntilConditionSpell (line 11) | public class DrawCardUntilConditionSpell extends Spell {
method onCast (line 13) | @Override
FILE: game/src/main/java/net/demilich/metastone/game/spells/EitherOrSpell.java
class EitherOrSpell (line 14) | public class EitherOrSpell extends Spell {
method create (line 16) | public static SpellDesc create(EntityReference target, SpellDesc eithe...
method create (line 25) | public static SpellDesc create(SpellDesc either, SpellDesc or, ISpel
Condensed preview — 2009 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,558K chars).
[
{
"path": ".gitignore",
"chars": 163,
"preview": "bin\n.settings\n.classpath\n.project\n.gradle\n.idea\ntest-output\nreport.log\n/~$card_checklist.xlsx\nbuild/\nclasses/\n*.iml\n\ncar"
},
{
"path": "LICENSE",
"chars": 18047,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
},
{
"path": "README.md",
"chars": 9268,
"preview": "# MetaStone #\r\n\r\n### What is it? ###\r\nMetaStone is a simulator for the online collectible card game (CCG) Hearthstone&re"
},
{
"path": "app/build.fxbuild",
"chars": 481,
"preview": "<?xml version=\"1.0\" encoding=\"ASCII\"?>\r\n<anttasks:AntTask xmi:version=\"2.0\" xmlns:xmi=\"http://www.omg.org/XMI\" xmlns:ant"
},
{
"path": "app/build.gradle",
"chars": 1221,
"preview": "apply plugin: 'java'\r\napply plugin: 'application'\r\napply plugin: 'javafx-gradle-plugin'\r\n\r\nbuildscript {\r\n dependenci"
},
{
"path": "app/javafx.plugin",
"chars": 3740,
"preview": "/*\n * Bootstrap script for the Gradle JavaFX Plugin.\n * (based on http://plugins.jasoft.fi/vaadin.plugin)\n *\n * The scri"
},
{
"path": "app/manifest.json",
"chars": 100,
"preview": "{\r\n\t\"version\" : \"1.2.0\",\r\n\t\"whatsNew\" : [\r\n\t\t\"- added all 'One Night in Karazhan' cards\"\r\n\t]\r\n\t\r\n}\r\n"
},
{
"path": "app/src/deploy/package/windows/Metastone.iss",
"chars": 2383,
"preview": ";This file will be executed next to the application bundle image\r\n;I.e. current directory will contain folder Metastone "
},
{
"path": "app/src/main/java/net/demilich/metastone/ApplicationFacade.java",
"chars": 5914,
"preview": "package net.demilich.metastone;\n\nimport net.demilich.nittygrittymvc.Facade;\nimport net.demilich.nittygrittymvc.interface"
},
{
"path": "app/src/main/java/net/demilich/metastone/ApplicationStartupCommand.java",
"chars": 1326,
"preview": "package net.demilich.metastone;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.demilich.nittygrittymvc.in"
},
{
"path": "app/src/main/java/net/demilich/metastone/DevCardTools.java",
"chars": 7641,
"preview": "package net.demilich.metastone;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileReader;\nimport j"
},
{
"path": "app/src/main/java/net/demilich/metastone/MetaStone.java",
"chars": 2247,
"preview": "package net.demilich.metastone;\r\n\r\nimport javafx.application.Application;\r\nimport javafx.geometry.Pos;\r\nimport javafx.sc"
},
{
"path": "app/src/main/java/net/demilich/metastone/PlayGameCommand.java",
"chars": 500,
"preview": "package net.demilich.metastone;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.demilich.nittygrittymvc.in"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/DigitFactory.java",
"chars": 3322,
"preview": "package net.demilich.metastone.gui;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.HashMap;\n\nimport "
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/DigitTemplate.java",
"chars": 559,
"preview": "package net.demilich.metastone.gui;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXML;\nimport javafx.fxml.FXMLLoader"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/IconFactory.java",
"chars": 3592,
"preview": "package net.demilich.metastone.gui;\n\nimport javafx.scene.image.Image;\nimport javafx.scene.paint.Color;\nimport net.demili"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/autoupdate/AutoUpdateMediator.java",
"chars": 2589,
"preview": "package net.demilich.metastone.gui.autoupdate;\r\n\r\nimport java.awt.Desktop;\r\nimport java.io.IOException;\r\nimport java.net"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/autoupdate/CheckForUpdateCommand.java",
"chars": 2272,
"preview": "package net.demilich.metastone.gui.autoupdate;\r\n\r\nimport org.apache.http.HttpEntity;\r\nimport org.apache.http.client.conf"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleBatchResult.java",
"chars": 1717,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport net.demilich.metastone.game.GameContext;\nimport net.demilich.m"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleBatchResultToken.java",
"chars": 2492,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXML;\nimport javafx.f"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleConfig.java",
"chars": 689,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport java.util.Collection;\n\nimport net.demilich.metastone.game.beha"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleDeckResult.java",
"chars": 1778,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport javafx.beans.property.DoubleProperty;\nimport javafx.beans.prop"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksConfigView.java",
"chars": 4756,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport java.io.IOException;\nimport java.util.Collection;\nimport java."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksMediator.java",
"chars": 2155,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demili"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleOfDecksResultView.java",
"chars": 3756,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport java.io.IOException;\nimport java.util.HashMap;\n\nimport javafx."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/BattleResult.java",
"chars": 1777,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.uti"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/battleofdecks/StartBattleOfDecksCommand.java",
"chars": 4449,
"preview": "package net.demilich.metastone.gui.battleofdecks;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.uti"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/cards/CardProxy.java",
"chars": 1267,
"preview": "package net.demilich.metastone.gui.cards;\r\n\r\nimport net.demilich.metastone.GameNotification;\r\nimport net.demilich.metast"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/cards/CardToken.java",
"chars": 4664,
"preview": "package net.demilich.metastone.gui.cards;\r\n\r\nimport java.io.IOException;\r\n\r\nimport javafx.fxml.FXML;\r\nimport javafx.fxml"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/cards/CardTokenFactory.java",
"chars": 874,
"preview": "package net.demilich.metastone.gui.cards;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demilich.metas"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/cards/CardTooltip.java",
"chars": 901,
"preview": "package net.demilich.metastone.gui.cards;\n\nimport javafx.fxml.FXML;\nimport javafx.scene.control.Label;\nimport net.demili"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/cards/HandCard.java",
"chars": 1885,
"preview": "package net.demilich.metastone.gui.cards;\n\nimport javafx.fxml.FXML;\nimport javafx.scene.control.Tooltip;\nimport javafx.s"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/common/BehaviourStringConverter.java",
"chars": 386,
"preview": "package net.demilich.metastone.gui.common;\n\nimport javafx.util.StringConverter;\nimport net.demilich.metastone.game.behav"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/common/CardSetStringConverter.java",
"chars": 380,
"preview": "package net.demilich.metastone.gui.common;\r\n\r\nimport javafx.util.StringConverter;\r\nimport net.demilich.metastone.game.ca"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/common/ComboBoxKeyHandler.java",
"chars": 1591,
"preview": "package net.demilich.metastone.gui.common;\r\n\r\nimport com.sun.javafx.scene.control.skin.ComboBoxListViewSkin;\r\n\r\nimport j"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/common/DeckFormatStringConverter.java",
"chars": 375,
"preview": "package net.demilich.metastone.gui.common;\n\nimport javafx.util.StringConverter;\nimport net.demilich.metastone.game.decks"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/common/DeckStringConverter.java",
"chars": 341,
"preview": "package net.demilich.metastone.gui.common;\n\nimport javafx.util.StringConverter;\nimport net.demilich.metastone.game.decks"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/common/HeroStringConverter.java",
"chars": 373,
"preview": "package net.demilich.metastone.gui.common;\n\nimport javafx.util.StringConverter;\nimport net.demilich.metastone.game.cards"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/common/IntegerTextField.java",
"chars": 792,
"preview": "package net.demilich.metastone.gui.common;\n\nimport javafx.beans.property.IntegerProperty;\nimport javafx.beans.property.S"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/common/RestrictedTextField.java",
"chars": 2100,
"preview": "package net.demilich.metastone.gui.common;\n\nimport javafx.beans.property.IntegerProperty;\nimport javafx.beans.property.S"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/AddCardToDeckCommand.java",
"chars": 685,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.demilich.n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardEntry.java",
"chars": 1127,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXML;\nimport javafx.fxm"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardEntryFactory.java",
"chars": 792,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demilich"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardFilter.java",
"chars": 580,
"preview": "package net.demilich.metastone.gui.deckbuilder;\r\n\r\nimport net.demilich.metastone.game.cards.CardSet;\r\nimport net.demilic"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardFilterView.java",
"chars": 3444,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.uti"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardListView.java",
"chars": 1854,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.util.HashMap;\n\nimport javafx.event.EventHandler;\nimport jav"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/CardView.java",
"chars": 3145,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.uti"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/ChangeDeckNameCommand.java",
"chars": 559,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.demilich.n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/ChooseClassView.java",
"chars": 3416,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.IOException;\n\nimport javafx.beans.value.ObservableValue;"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckBuilderMediator.java",
"chars": 3153,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demilich"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckBuilderView.java",
"chars": 4326,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport javafx.event.ActionEvent;\nimport javafx.event.EventHandler;\nimpo"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckEntry.java",
"chars": 2013,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.IOException;\n\nimport javafx.event.ActionEvent;\nimport ja"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckFormatProxy.java",
"chars": 3159,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimpor"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckInfoView.java",
"chars": 3619,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.IOException;\n\nimport javafx.event.ActionEvent;\nimport ja"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckListView.java",
"chars": 1686,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport javafx.event"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckNameView.java",
"chars": 1366,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.IOException;\n\nimport javafx.beans.value.ChangeListener;\n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeckProxy.java",
"chars": 9992,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/DeleteDeckCommand.java",
"chars": 591,
"preview": "package net.demilich.metastone.gui.deckbuilder;\r\n\r\nimport net.demilich.metastone.GameNotification;\r\nimport net.demilich."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/FillDeckWithRandomCardsCommand.java",
"chars": 1467,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.util.List;\nimport java.util.concurrent.ThreadLocalRandom;\n\n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/FilterCardsCommand.java",
"chars": 1738,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.util.List;\n\nimport org.apache.commons.lang3.StringUtils;\n\ni"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/ImportDeckCommand.java",
"chars": 1446,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport net.demilich.metastone.gui.deckbuilder.importer.ImporterFactory;"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/LoadDeckFormatsCommand.java",
"chars": 909,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimpor"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/LoadDecksCommand.java",
"chars": 848,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimpor"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/RemoveCardFromDeckCommand.java",
"chars": 699,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.demilich.n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/SaveDeckCommand.java",
"chars": 1012,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.demilich.n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/SetActiveDeckCommand.java",
"chars": 1186,
"preview": "package net.demilich.metastone.gui.deckbuilder;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.demilich.n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/HearthHeadImporter.java",
"chars": 2554,
"preview": "package net.demilich.metastone.gui.deckbuilder.importer;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/HearthPwnImporter.java",
"chars": 3466,
"preview": "package net.demilich.metastone.gui.deckbuilder.importer;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/IDeckImporter.java",
"chars": 173,
"preview": "package net.demilich.metastone.gui.deckbuilder.importer;\n\nimport net.demilich.metastone.game.decks.Deck;\n\npublic interfa"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/IcyVeinsImporter.java",
"chars": 3012,
"preview": "package net.demilich.metastone.gui.deckbuilder.importer;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/ImporterFactory.java",
"chars": 597,
"preview": "package net.demilich.metastone.gui.deckbuilder.importer;\n\npublic class ImporterFactory {\n\n public IDeckImporter creat"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/importer/TempostormImporter.java",
"chars": 3872,
"preview": "package net.demilich.metastone.gui.deckbuilder.importer;\n\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonE"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/AddDeckToMetaDeckCommand.java",
"chars": 915,
"preview": "package net.demilich.metastone.gui.deckbuilder.metadeck;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.d"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/MetaDeckListView.java",
"chars": 1442,
"preview": "package net.demilich.metastone.gui.deckbuilder.metadeck;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport jav"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/MetaDeckView.java",
"chars": 2007,
"preview": "package net.demilich.metastone.gui.deckbuilder.metadeck;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport jav"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/deckbuilder/metadeck/RemoveDeckFromMetaDeckCommand.java",
"chars": 925,
"preview": "package net.demilich.metastone.gui.deckbuilder.metadeck;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.d"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/dialog/DialogMediator.java",
"chars": 2475,
"preview": "package net.demilich.metastone.gui.dialog;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.slf4j.Logger;"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/dialog/DialogNotification.java",
"chars": 865,
"preview": "package net.demilich.metastone.gui.dialog;\n\nimport net.demilich.nittygrittymvc.Notification;\nimport net.demilich.metasto"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/dialog/DialogResult.java",
"chars": 86,
"preview": "package net.demilich.metastone.gui.dialog;\n\npublic enum DialogResult {\n\n\tOK, CANCEL\n}\n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/dialog/DialogType.java",
"chars": 103,
"preview": "package net.demilich.metastone.gui.dialog;\n\npublic enum DialogType {\n\tCONFIRM, INFO, WARNING, ERROR,\n}\n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/dialog/IDialogListener.java",
"chars": 126,
"preview": "package net.demilich.metastone.gui.dialog;\n\npublic interface IDialogListener {\n\n\tvoid onDialogClosed(DialogResult result"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/dialog/ModalDialog.java",
"chars": 799,
"preview": "package net.demilich.metastone.gui.dialog;\n\nimport javafx.scene.Node;\nimport javafx.scene.Scene;\nimport javafx.scene.lay"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/dialog/UserDialog.java",
"chars": 1745,
"preview": "package net.demilich.metastone.gui.dialog;\n\nimport java.io.IOException;\n\nimport javafx.event.ActionEvent;\nimport javafx."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/gameconfig/PlayerConfigView.java",
"chars": 6750,
"preview": "package net.demilich.metastone.gui.gameconfig;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/main/ApplicationMediator.java",
"chars": 2403,
"preview": "package net.demilich.metastone.gui.main;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javafx.scene.Node;\n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/mainmenu/MainMenuMediator.java",
"chars": 2449,
"preview": "package net.demilich.metastone.gui.mainmenu;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demilich.ni"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/mainmenu/MainMenuView.java",
"chars": 2554,
"preview": "package net.demilich.metastone.gui.mainmenu;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.net.URISyntax"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/GameBoardView.java",
"chars": 9136,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Lis"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/GameContextVisualizable.java",
"chars": 1991,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demilich.me"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/GameToken.java",
"chars": 3464,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.io.IOException;\n\nimport javafx.beans.binding.Bindings;\nimport "
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/HeroToken.java",
"chars": 5282,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.util.HashSet;\n\nimport javafx.fxml.FXML;\nimport javafx.scene.Gr"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/HumanActionPromptView.java",
"chars": 7066,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/HumanMulliganView.java",
"chars": 3010,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.H"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/LoadingBoardView.java",
"chars": 667,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXML;\nimport javafx.fxml.F"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/PlayModeMediator.java",
"chars": 3064,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demilich.ni"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/PlayModeView.java",
"chars": 2228,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXML;\nimport javafx.fxml.F"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/StartGameCommand.java",
"chars": 1367,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport net.demilich.metastone.NotificationProxy;\nimport net.demilich.nitty"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/SummonToken.java",
"chars": 2662,
"preview": "package net.demilich.metastone.gui.playmode;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javafx.fx"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/AnimationCompletedCommand.java",
"chars": 522,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.dem"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/AnimationLockCommand.java",
"chars": 695,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.dem"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/AnimationProxy.java",
"chars": 793,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport net.demilich.nittygrittymvc.Proxy;\nimport net.demilich.me"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/AnimationStartedCommand.java",
"chars": 518,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.dem"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/CardPlayedToken.java",
"chars": 1426,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport javafx.animation.FadeTransition;\nimport javafx.event.Acti"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/CardRevealedToken.java",
"chars": 1925,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport javafx.animation.FadeTransition;\nimport javafx.event.Acti"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/DamageEventVisualizer.java",
"chars": 1489,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport java.util.HashMap;\n\nimport net.demilich.metastone.game.Ga"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/DamageNumber.java",
"chars": 1763,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport javafx.animation.PauseTransition;\nimport javafx.event.Act"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/EventVisualizerDispatcher.java",
"chars": 1504,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport java.util.HashMap;\n\nimport net.demilich.metastone.GameNot"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/HealEventVisualizer.java",
"chars": 730,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport net.demilich.metastone.game.GameContext;\nimport net.demil"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/HealingNumber.java",
"chars": 1267,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport javafx.animation.TranslateTransition;\nimport javafx.event"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/IAnimationListener.java",
"chars": 167,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\npublic interface IAnimationListener {\n\n\tpublic void animationCom"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/IGameEventVisualizer.java",
"chars": 348,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport net.demilich.metastone.game.GameContext;\nimport net.demil"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/JoustToken.java",
"chars": 1859,
"preview": "package net.demilich.metastone.gui.playmode.animation;\r\n\r\nimport javafx.animation.FadeTransition;\r\nimport javafx.animati"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/JoustVisualizer.java",
"chars": 1122,
"preview": "package net.demilich.metastone.gui.playmode.animation;\r\n\r\nimport net.demilich.metastone.game.GameContext;\r\nimport net.de"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/PlayCardVisualizer.java",
"chars": 707,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport net.demilich.metastone.game.Attribute;\nimport net.demilic"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/animation/RevealCardVisualizer.java",
"chars": 753,
"preview": "package net.demilich.metastone.gui.playmode.animation;\n\nimport net.demilich.metastone.game.Attribute;\nimport net.demilic"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/config/PlayModeConfigMediator.java",
"chars": 2208,
"preview": "package net.demilich.metastone.gui.playmode.config;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demi"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/config/PlayModeConfigView.java",
"chars": 3483,
"preview": "package net.demilich.metastone.gui.playmode.config;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport javafx.b"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/config/PlayerConfigType.java",
"chars": 125,
"preview": "package net.demilich.metastone.gui.playmode.config;\n\npublic enum PlayerConfigType {\n\n\tHUMAN, OPPONENT, SIMULATION, SANDB"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/config/RequestDeckFormatsCommand.java",
"chars": 845,
"preview": "package net.demilich.metastone.gui.playmode.config;\n\nimport java.util.List;\n\nimport net.demilich.nittygrittymvc.SimpleCo"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/playmode/config/RequestDecksCommand.java",
"chars": 757,
"preview": "package net.demilich.metastone.gui.playmode.config;\n\nimport java.util.List;\n\nimport net.demilich.nittygrittymvc.SimpleCo"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/CardCollectionEditor.java",
"chars": 4277,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport javafx.beans.value.ObservableValue;\nimport javafx.collections.FX"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/CardPanel.java",
"chars": 2312,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.io.IOException;\n\nimport javafx.event.ActionEvent;\nimport ja"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/EntityEditor.java",
"chars": 5887,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.util.EnumMap;\nimport java.util.Map;\n\nimport javafx.beans.pr"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/GameTagEntry.java",
"chars": 836,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport net.demilich.metastone.game.Attribute;\nimport net.demilich.metas"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/ICardCollectionEditingListener.java",
"chars": 217,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport net.demilich.metastone.game.cards.CardCollection;\n\npublic interf"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/MinionPanel.java",
"chars": 3469,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.io.IOException;\n\nimport javafx.beans.value.ObservableValue;"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/PlayerPanel.java",
"chars": 4330,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.io.IOException;\n\nimport javafx.beans.value.ObservableValue;"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxEditor.java",
"chars": 791,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXML;\nimport javafx.fxm"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxModeConfigView.java",
"chars": 3464,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport javafx.beans"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxModeMediator.java",
"chars": 4043,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demilich"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxModeView.java",
"chars": 3887,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.io.IOException;\n\nimport javafx.event.ActionEvent;\nimport ja"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/SandboxProxy.java",
"chars": 753,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport net.demilich.nittygrittymvc.Proxy;\nimport net.demilich.metastone"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/ToolboxView.java",
"chars": 1240,
"preview": "package net.demilich.metastone.gui.sandboxmode;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXMLLoader;\nimport java"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/EditEntityAction.java",
"chars": 1188,
"preview": "package net.demilich.metastone.gui.sandboxmode.actions;\n\nimport net.demilich.metastone.GameNotification;\nimport net.demi"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/KillAction.java",
"chars": 868,
"preview": "package net.demilich.metastone.gui.sandboxmode.actions;\n\nimport net.demilich.metastone.game.GameContext;\nimport net.demi"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/SetManaAction.java",
"chars": 843,
"preview": "package net.demilich.metastone.gui.sandboxmode.actions;\n\nimport net.demilich.metastone.game.GameContext;\nimport net.demi"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/SetMaxManaAction.java",
"chars": 852,
"preview": "package net.demilich.metastone.gui.sandboxmode.actions;\n\nimport net.demilich.metastone.game.GameContext;\nimport net.demi"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/actions/SilenceAction.java",
"chars": 893,
"preview": "package net.demilich.metastone.gui.sandboxmode.actions;\n\nimport net.demilich.metastone.game.GameContext;\nimport net.demi"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/CreateNewSandboxCommand.java",
"chars": 2121,
"preview": "package net.demilich.metastone.gui.sandboxmode.commands;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.d"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/ModifyPlayerDeckCommand.java",
"chars": 1201,
"preview": "package net.demilich.metastone.gui.sandboxmode.commands;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.d"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/ModifyPlayerHandCommand.java",
"chars": 1199,
"preview": "package net.demilich.metastone.gui.sandboxmode.commands;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.d"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/PerformActionCommand.java",
"chars": 2382,
"preview": "package net.demilich.metastone.gui.sandboxmode.commands;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/SelectPlayerCommand.java",
"chars": 668,
"preview": "package net.demilich.metastone.gui.sandboxmode.commands;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.d"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/SpawnMinionCommand.java",
"chars": 2672,
"preview": "package net.demilich.metastone.gui.sandboxmode.commands;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/StartPlaySandboxCommand.java",
"chars": 669,
"preview": "package net.demilich.metastone.gui.sandboxmode.commands;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.d"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/sandboxmode/commands/StopPlaySandboxCommand.java",
"chars": 748,
"preview": "package net.demilich.metastone.gui.sandboxmode.commands;\n\nimport net.demilich.nittygrittymvc.SimpleCommand;\nimport net.d"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/PlayerConfigView.java",
"chars": 312,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport net.demilich.metastone.gui.playmode.config.PlayerConfigType;\n"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/PlayerInfoView.java",
"chars": 1235,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXML;\nimport javafx."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulateGamesCommand.java",
"chars": 4566,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulationMediator.java",
"chars": 3229,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.slf4j"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulationModeConfigView.java",
"chars": 3963,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport javafx.be"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulationResult.java",
"chars": 1481,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport net.demilich.metastone.game.statistics.GameStatistics;\nimport"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/SimulationResultView.java",
"chars": 7550,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport java.io.IOException;\nimport java.text.DecimalFormat;\nimport j"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/StatEntry.java",
"chars": 1281,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport javafx.beans.property.SimpleStringProperty;\nimport javafx.bea"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/simulationmode/WaitForSimulationView.java",
"chars": 928,
"preview": "package net.demilich.metastone.gui.simulationmode;\n\nimport java.io.IOException;\n\nimport javafx.fxml.FXML;\nimport javafx."
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/PerformTrainingCommand.java",
"chars": 3820,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\nimport net.demilich.metastone.trainingmode.TrainingData;\nimport org.sl"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/RequestTrainingDataCommand.java",
"chars": 1374,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\nimport net.demilich.metastone.trainingmode.ITrainingDataListener;\nimpo"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/SaveTrainingDataCommand.java",
"chars": 650,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\nimport net.demilich.metastone.trainingmode.TrainingData;\nimport net.de"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingConfig.java",
"chars": 800,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.co"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingConfigView.java",
"chars": 4442,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.u"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingModeMediator.java",
"chars": 2461,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.demilic"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingModeView.java",
"chars": 2378,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\nimport java.io.IOException;\n\nimport javafx.event.ActionEvent;\nimport j"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingProgressReport.java",
"chars": 543,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\npublic class TrainingProgressReport {\n\n\tprivate final int gamesComplet"
},
{
"path": "app/src/main/java/net/demilich/metastone/gui/trainingmode/TrainingProxy.java",
"chars": 4485,
"preview": "package net.demilich.metastone.gui.trainingmode;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/CardCreator.java",
"chars": 662,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport javafx.application.Application;\r\nimport javafx.scene.Scene;\r\nimport java"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/CardEditor.java",
"chars": 1820,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport java.io.File;\r\nimport java.io.IOException;\r\n\r\nimport org.apache.commons."
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/EditorMainWindow.java",
"chars": 9965,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport java.awt.Desktop;\r\nimport java.io.File;\r\nimport java.io.IOException;\r\nim"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/ICardEditor.java",
"chars": 252,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport javafx.scene.Node;\r\nimport net.demilich.metastone.game.cards.desc.CardDe"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/ITextFieldAction.java",
"chars": 114,
"preview": "package net.demilich.metastone.tools;\r\n\r\ninterface ITextFieldAction {\r\n\r\n\tpublic void onChanged(int value);\r\n\r\n}\r\n"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/IntegerListener.java",
"chars": 692,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport javafx.beans.value.ChangeListener;\r\nimport javafx.beans.value.Observable"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/MinionCardPanel.java",
"chars": 3577,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport javafx.beans.value.ObservableValue;\r\nimport javafx.collections.FXCollect"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/SpellCardPanel.java",
"chars": 1897,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport javafx.beans.value.ObservableValue;\r\nimport javafx.collections.FXCollect"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/SpellDescSerializer.java",
"chars": 1102,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport java.lang.reflect.Type;\r\n\r\nimport com.google.gson.JsonElement;\r\nimport c"
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/SpellStringConverter.java",
"chars": 420,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport javafx.util.StringConverter;\r\nimport net.demilich.metastone.game.spells."
},
{
"path": "app/src/main/java/net/demilich/metastone/tools/WeaponClassPanel.java",
"chars": 619,
"preview": "package net.demilich.metastone.tools;\r\n\r\nimport net.demilich.metastone.game.cards.CardType;\r\nimport net.demilich.metasto"
},
{
"path": "app/src/main/resources/css/deckbuilder.css",
"chars": 709,
"preview": ".class-button {\n\t-fx-font-size: 20pt;\n -fx-font-family: \"System\";\n}\n\n.card-entry-name {\n\t-fx-font-size: 10pt;\n -fx"
},
{
"path": "app/src/main/resources/css/gameboard.css",
"chars": 278,
"preview": ".board {\n\t-fx-background-color: bisque;\n}\n\n.center-message {\n\t-fx-font-size: 20pt;\n -fx-font-family: \"System\";\n -f"
},
{
"path": "app/src/main/resources/css/main.css",
"chars": 4783,
"preview": ".button {\n\t-fx-background-color:\n #090a0c,\n linear-gradient(#38424b 0%, #1f2429 20%, #191d22 100%),\n "
},
{
"path": "app/src/main/resources/css/mainmenu.css",
"chars": 469,
"preview": ".title {\n\t-fx-font-size: 32pt;\n -fx-font-family: \"System\";\n -fx-font-weight: bold;\n -fx-effect: dropshadow(one-"
},
{
"path": "app/src/main/resources/fxml/BattleBatchResultToken.fxml",
"chars": 3482,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.chart.*?>\n<?import java.net.*?>\n<?import javafx.scene.imag"
},
{
"path": "app/src/main/resources/fxml/BattleOfDecksConfigView.fxml",
"chars": 3385,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.net.*?>\n<?import javafx.scene.image.*?>\n<?import javafx.geometry.*"
},
{
"path": "app/src/main/resources/fxml/BattleOfDecksResultView.fxml",
"chars": 2089,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.chart.*?>\n<?import java.net.*?>\n<?import javafx.scene.imag"
},
{
"path": "app/src/main/resources/fxml/CardCollectionEditor.fxml",
"chars": 3643,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.chart.*?>\n<?import java.net.*?>\n<?import javafx.scene.imag"
},
{
"path": "app/src/main/resources/fxml/CardEntry.fxml",
"chars": 1303,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.control.*?>\n<?import java.net.*?>\n<?import javafx.scene.te"
},
{
"path": "app/src/main/resources/fxml/CardFilterView.fxml",
"chars": 1334,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.image.*?>\n<?import javafx.geometry.*?>\n<?import java.net.*"
},
{
"path": "app/src/main/resources/fxml/CardPanel.fxml",
"chars": 691,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.chart.*?>\n<?import java.net.*?>\n<?import javafx.scene.imag"
},
{
"path": "app/src/main/resources/fxml/CardTooltip.fxml",
"chars": 2929,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.*?>\n<?import javafx.scene.shape.*?>\n<?import java.lang.*?>"
},
{
"path": "app/src/main/resources/fxml/CardView.fxml",
"chars": 1401,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.image.*?>\n<?import javafx.geometry.*?>\n<?import java.net.*"
},
{
"path": "app/src/main/resources/fxml/ChooseClassView.fxml",
"chars": 7420,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.effect.*?>\n<?import java.net.*?>\n<?import javafx.scene.ima"
},
{
"path": "app/src/main/resources/fxml/DeckBuilderView.fxml",
"chars": 2938,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.net.URL?>\n<?import javafx.geometry.Insets?>\n<?import javafx.scene."
},
{
"path": "app/src/main/resources/fxml/DeckEntry.fxml",
"chars": 1632,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.net.URL?>\n<?import javafx.scene.control.Button?>\n<?import javafx.s"
},
{
"path": "app/src/main/resources/fxml/DeckInfoView.fxml",
"chars": 1071,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.net.*?>\n<?import javafx.scene.control.*?>\n<?import java.lang.*?>\n<"
},
{
"path": "app/src/main/resources/fxml/DeckListView.fxml",
"chars": 1111,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.geometry.Insets?>\n<?import javafx.scene.control.Button?>\n<?impor"
},
{
"path": "app/src/main/resources/fxml/DeckNameView.fxml",
"chars": 935,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.image.*?>\n<?import java.net.*?>\n<?import javafx.scene.cont"
},
{
"path": "app/src/main/resources/fxml/DigitTemplate.fxml",
"chars": 639,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.paint.*?>\n<?import javafx.scene.shape.*?>\n<?import java.la"
},
{
"path": "app/src/main/resources/fxml/EditorMainWindow.fxml",
"chars": 6749,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.web.*?>\n<?import javafx.scene.image.*?>\n<?import java.net."
},
{
"path": "app/src/main/resources/fxml/EntityEditor.fxml",
"chars": 1869,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.chart.*?>\n<?import java.net.*?>\n<?import javafx.scene.imag"
},
{
"path": "app/src/main/resources/fxml/GameBoardView.fxml",
"chars": 1909,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.lang.*?>\n<?import java.net.*?>\n<?import javafx.geometry.*?>\n<?impo"
},
{
"path": "app/src/main/resources/fxml/HandCard.fxml",
"chars": 2609,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.*?>\n<?import javafx.scene.paint.*?>\n<?import javafx.scene."
},
{
"path": "app/src/main/resources/fxml/HeroToken.fxml",
"chars": 5283,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.*?>\n<?import java.lang.*?>\n<?import java.net.*?>\n<?import "
}
]
// ... and 1809 more files (download for full content)
About this extraction
This page contains the full source code of the demilich1/metastone GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 2009 files (2.0 MB), approximately 649.1k tokens, and a symbol index with 3255 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.