package net.demilich.metastone.game.cards.desc; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import net.demilich.metastone.game.Attribute; import net.demilich.metastone.game.PlayerAttribute; import net.demilich.metastone.game.actions.ActionType; import net.demilich.metastone.game.cards.CardDescType; import net.demilich.metastone.game.cards.CardType; import net.demilich.metastone.game.cards.Rarity; import net.demilich.metastone.game.entities.EntityType; import net.demilich.metastone.game.entities.heroes.HeroClass; import net.demilich.metastone.game.entities.minions.Race; import net.demilich.metastone.game.entities.minions.RelativeToSource; import net.demilich.metastone.game.spells.TargetPlayer; import net.demilich.metastone.game.spells.desc.SpellDesc; import net.demilich.metastone.game.spells.desc.condition.Condition; import net.demilich.metastone.game.spells.desc.condition.ConditionDesc; import net.demilich.metastone.game.spells.desc.filter.EntityFilter; import net.demilich.metastone.game.spells.desc.filter.FilterDesc; import net.demilich.metastone.game.spells.desc.filter.Operation; import net.demilich.metastone.game.spells.desc.manamodifier.CardCostModifierDesc; import net.demilich.metastone.game.spells.desc.source.SourceDesc; import net.demilich.metastone.game.spells.desc.trigger.EventTriggerDesc; import net.demilich.metastone.game.spells.desc.trigger.EventTriggerDeserializer; import net.demilich.metastone.game.spells.desc.trigger.TriggerDesc; import net.demilich.metastone.game.spells.desc.valueprovider.AlgebraicOperation; import net.demilich.metastone.game.spells.desc.valueprovider.ValueProviderDesc; import net.demilich.metastone.game.targeting.CardLocation; import net.demilich.metastone.game.targeting.EntityReference; import net.demilich.metastone.game.targeting.TargetSelection; import net.demilich.metastone.game.targeting.TargetType; public class ParseUtils { private static SpellDeserializer spellParser = new SpellDeserializer(); private static ValueProviderDeserializer valueProviderParser = new ValueProviderDeserializer(); private static FilterDeserializer filterParser = new FilterDeserializer(); private static SourceDeserializer sourceParser = new SourceDeserializer(); private static ConditionDeserializer conditionParser = new ConditionDeserializer(); private static EventTriggerDeserializer triggerParser = new EventTriggerDeserializer(); private static CardCostModifierDeserializer manaModifierParser = new CardCostModifierDeserializer(); public static Object parse(String argName, JsonObject jsonData, ParseValueType valueType) { JsonElement entry = jsonData.get(argName); switch (valueType) { case INTEGER: return entry.getAsInt(); case BOOLEAN: return entry.getAsBoolean(); case STRING: return entry.getAsString(); case STRING_ARRAY: { JsonArray jsonArray = entry.getAsJsonArray(); String[] array = new String[jsonArray.size()]; for (int i = 0; i < array.length; i++) { array[i] = jsonArray.get(i).getAsString(); } return array; } case TARGET_SELECTION: return Enum.valueOf(TargetSelection.class, entry.getAsString()); case TARGET_REFERENCE: return parseEntityReference(entry.getAsString()); case TARGET_PLAYER: return Enum.valueOf(TargetPlayer.class, entry.getAsString()); case RACE: return Enum.valueOf(Race.class, entry.getAsString()); case SPELL: return spellParser.deserialize(entry, SpellDesc.class, null); case SPELL_ARRAY: { JsonArray jsonArray = entry.getAsJsonArray(); SpellDesc[] array = new SpellDesc[jsonArray.size()]; for (int i = 0; i < array.length; i++) { array[i] = spellParser.deserialize(jsonArray.get(i), SpellDesc.class, null); } return array; } case ATTRIBUTE: return Enum.valueOf(Attribute.class, entry.getAsString()); case PLAYER_ATTRIBUTE: return Enum.valueOf(PlayerAttribute.class, entry.getAsString()); case RARITY: return Enum.valueOf(Rarity.class, entry.getAsString()); case HERO_CLASS: return Enum.valueOf(HeroClass.class, entry.getAsString()); case HERO_CLASS_ARRAY: { JsonArray jsonArray = entry.getAsJsonArray(); HeroClass[] array = new HeroClass[jsonArray.size()]; for (int i = 0; i < array.length; i++) { array[i] = Enum.valueOf(HeroClass.class, jsonArray.get(i).getAsString()); } return array; } case BOARD_POSITION_RELATIVE: return Enum.valueOf(RelativeToSource.class, entry.getAsString()); case CARD_LOCATION: return Enum.valueOf(CardLocation.class, entry.getAsString()); case OPERATION: return Enum.valueOf(Operation.class, entry.getAsString()); case CARD_TYPE: return Enum.valueOf(CardType.class, entry.getAsString()); case ENTITY_TYPE: return Enum.valueOf(EntityType.class, entry.getAsString()); case ACTION_TYPE: return Enum.valueOf(ActionType.class, entry.getAsString()); case TARGET_TYPE: return Enum.valueOf(TargetType.class, entry.getAsString()); case CARD_DESC_TYPE: return Enum.valueOf(CardDescType.class, entry.getAsString()); case ALGEBRAIC_OPERATION: return Enum.valueOf(AlgebraicOperation.class, entry.getAsString()); case VALUE: // value is either an int or a ValueProvider // if it is not an object, parse it as int, else fall-through to VALUE_PROVIDER case if (!entry.isJsonObject()) { return entry.getAsInt(); } case VALUE_PROVIDER: ValueProviderDesc valueProviderDesc = valueProviderParser.deserialize(entry, ValueProviderDesc.class, null); return valueProviderDesc.create(); case ENTITY_FILTER: { FilterDesc filterDesc = filterParser.deserialize(entry, FilterDesc.class, null); return filterDesc.create(); } case CARD_SOURCE: { SourceDesc sourceDesc = sourceParser.deserialize(entry, SourceDesc.class, null); return sourceDesc.create(); } case ENTITY_FILTER_ARRAY: { JsonArray jsonArray = entry.getAsJsonArray(); EntityFilter[] array = new EntityFilter[jsonArray.size()]; for (int i = 0; i < array.length; i++) { FilterDesc filterDesc = filterParser.deserialize(jsonArray.get(i), FilterDesc.class, null); array[i] = filterDesc.create(); } return array; } case CONDITION: { ConditionDesc conditionDesc = conditionParser.deserialize(entry, ConditionDesc.class, null); return conditionDesc.create(); } case CONDITION_ARRAY: { JsonArray jsonArray = entry.getAsJsonArray(); Condition[] array = new Condition[jsonArray.size()]; for (int i = 0; i < array.length; i++) { ConditionDesc conditionDesc = conditionParser.deserialize(jsonArray.get(i), ConditionDesc.class, null); array[i] = conditionDesc.create(); } return array; } case TRIGGER: JsonObject triggerObject = entry.getAsJsonObject(); TriggerDesc triggerDesc = new TriggerDesc(); triggerDesc.eventTrigger = triggerParser.deserialize(triggerObject.get("eventTrigger"), EventTriggerDesc.class, null); triggerDesc.spell = spellParser.deserialize(triggerObject.get("spell"), SpellDesc.class, null); triggerDesc.oneTurn = triggerObject.has("oneTurn") ? triggerObject.get("oneTurn").getAsBoolean() : false; triggerDesc.persistentOwner = triggerObject.has("persistentOwner") ? triggerObject.get("persistentOwner").getAsBoolean() : false; triggerDesc.turnDelay = triggerObject.has("turnDelay") ? triggerObject.get("turnDelay").getAsInt() : 0; return triggerDesc; case EVENT_TRIGGER: return triggerParser.deserialize(entry, EventTriggerDesc.class, null); case CARD_COST_MODIFIER: return manaModifierParser.deserialize(entry, CardCostModifierDesc.class, null); default: break; } return null; } private static EntityReference parseEntityReference(String str) { String lowerCaseName = str.toLowerCase(); switch (lowerCaseName) { case "none": return EntityReference.NONE; case "enemy_characters": return EntityReference.ENEMY_CHARACTERS; case "enemy_minions": return EntityReference.ENEMY_MINIONS; case "enemy_hero": return EntityReference.ENEMY_HERO; case "enemy_weapon": return EntityReference.ENEMY_WEAPON; case "friendly_characters": return EntityReference.FRIENDLY_CHARACTERS; case "friendly_minions": return EntityReference.FRIENDLY_MINIONS; case "other_friendly_minions": return EntityReference.OTHER_FRIENDLY_MINIONS; case "adjacent_minions": return EntityReference.ADJACENT_MINIONS; case "opposite_minions": return EntityReference.OPPOSITE_MINIONS; case "friendly_hero": return EntityReference.FRIENDLY_HERO; case "friendly_weapon": return EntityReference.FRIENDLY_WEAPON; case "all_minions": return EntityReference.ALL_MINIONS; case "all_characters": return EntityReference.ALL_CHARACTERS; case "all_other_characters": return EntityReference.ALL_OTHER_CHARACTERS; case "all_other_minions": return EntityReference.ALL_OTHER_MINIONS; case "event_target": return EntityReference.EVENT_TARGET; case "target": return EntityReference.TARGET; case "spell_target": return EntityReference.SPELL_TARGET; case "pending_card": return EntityReference.PENDING_CARD; case "event_card": return EntityReference.EVENT_CARD; case "self": return EntityReference.SELF; case "attacker": return EntityReference.ATTACKER_REFERENCE; case "friendly_hand": return EntityReference.FRIENDLY_HAND; case "enemy_hand": return EntityReference.ENEMY_HAND; case "leftmost_friendly_minion": return EntityReference.LEFTMOST_FRIENDLY_MINION; case "leftmost_enemy_minion": return EntityReference.LEFTMOST_ENEMY_MINION; case "friendly_player": return EntityReference.FRIENDLY_PLAYER; case "enemy_player": return EntityReference.ENEMY_PLAYER; case "minions_to_left": return EntityReference.MINIONS_TO_LEFT; case "minions_to_right": return EntityReference.MINIONS_TO_RIGHT; default: return null; } } public static String toCamelCase(String input) { String inputLowerCase = input.toLowerCase(); StringBuilder sb = new StringBuilder(); final char delim = '_'; char value; boolean capitalize = false; for (int i = 0; i < inputLowerCase.length(); ++i) { value = inputLowerCase.charAt(i); if (value == delim) { capitalize = true; } else if (capitalize) { sb.append(Character.toUpperCase(value)); capitalize = false; } else { sb.append(value); } } return sb.toString(); } public static boolean tryParseBool(String value) { try { Boolean.parseBoolean(value); return true; } catch (Exception e) { return false; } } public static boolean tryParseInt(String value) { try { Integer.parseInt(value); return true; } catch (Exception e) { return false; } } }