Updates monster imports from tetra cube.

This commit is contained in:
2026-09-07 20:10:36 -07:00
parent 044202cb3a
commit 2af18cbf1d
10 changed files with 10846 additions and 21 deletions

View File

@@ -20,7 +20,7 @@ import com.majinnaibu.monstercards.models.DashboardMonster;
import com.majinnaibu.monstercards.models.Monster;
import com.majinnaibu.monstercards.models.MonsterFTS;
@Database(entities = {Monster.class, MonsterFTS.class, Collection.class, CollectionMonster.class, DashboardMonster.class}, version = 5)
@Database(entities = {Monster.class, MonsterFTS.class, Collection.class, CollectionMonster.class, DashboardMonster.class}, version = 6)
@TypeConverters({
ArmorTypeConverter.class,
ChallengeRatingConverter.class,

View File

@@ -52,6 +52,20 @@ public class MonsterCardsApplication extends Application {
database.execSQL("INSERT INTO dashboard_monsters(monster_id, ordinal) SELECT id, 0 FROM monsters");
}
};
private static final Migration MIGRATION_5_6 = new Migration(5, 6) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE monsters ADD COLUMN `source_url` TEXT DEFAULT ''");
database.execSQL("ALTER TABLE monsters ADD COLUMN `bonus_actions` TEXT DEFAULT '[]'");
database.execSQL("ALTER TABLE monsters ADD COLUMN `mythic_actions` TEXT DEFAULT '[]'");
database.execSQL("ALTER TABLE monsters ADD COLUMN `legendary_actions_description` TEXT DEFAULT ''");
database.execSQL("ALTER TABLE monsters ADD COLUMN `lair_actions_description` TEXT DEFAULT ''");
database.execSQL("ALTER TABLE monsters ADD COLUMN `lair_actions_end_note` TEXT DEFAULT ''");
database.execSQL("ALTER TABLE monsters ADD COLUMN `regional_actions_description` TEXT DEFAULT ''");
database.execSQL("ALTER TABLE monsters ADD COLUMN `regional_actions_end_note` TEXT DEFAULT ''");
database.execSQL("ALTER TABLE monsters ADD COLUMN `mythic_actions_description` TEXT DEFAULT ''");
}
};
private MonsterRepository m_monsterLibraryRepository;
@@ -75,6 +89,7 @@ public class MonsterCardsApplication extends Application {
.addMigrations(MIGRATION_2_3)
.addMigrations(MIGRATION_3_4)
.addMigrations(MIGRATION_4_5)
.addMigrations(MIGRATION_5_6)
.fallbackToDestructiveMigrationOnDowngrade()
// .fallbackToDestructiveMigration()
.build();

View File

@@ -36,7 +36,9 @@ public class TetraCubeMonsterImporter implements EntityImporter<Monster> {
return false;
}
JsonObject rootDict = element.getAsJsonObject();
return rootDict.has("hitDice") || rootDict.has("armorName") || rootDict.has("strPoints");
return rootDict.has("hitDice") || rootDict.has("armorName") || rootDict.has("strPoints")
|| rootDict.has("bonusActions") || rootDict.has("isLegendary") || rootDict.has("isMythic")
|| rootDict.has("legendariesDescription");
} catch (Exception e) {
return false;
}
@@ -85,10 +87,46 @@ public class TetraCubeMonsterImporter implements EntityImporter<Monster> {
monster.abilities = getListOfTraits(rootDict, "abilities");
monster.actions = getListOfTraits(rootDict, "actions");
monster.bonusActions = getListOfTraits(rootDict, "bonusActions");
monster.reactions = getListOfTraits(rootDict, "reactions");
monster.legendaryActions = getListOfTraits(rootDict, "legendaries");
monster.mythicActions = getListOfTraits(rootDict, "mythics");
monster.lairActions = getListOfTraits(rootDict, "lairs");
monster.regionalActions = getListOfTraits(rootDict, "regionals");
monster.legendaryActionsDescription = getString(rootDict, "legendariesDescription");
if (!monster.legendaryActionsDescription.isEmpty()) {
monster.legendaryActions.add(0, new Trait("Legendary Actions", monster.legendaryActionsDescription));
}
monster.mythicActionsDescription = getString(rootDict, "mythicDescription");
if (!monster.mythicActionsDescription.isEmpty() || !monster.mythicActions.isEmpty()) {
if (!monster.mythicActionsDescription.isEmpty()) {
monster.legendaryActions.add(new Trait("Mythic Actions", monster.mythicActionsDescription));
}
for (Trait mythic : monster.mythicActions) {
String traitName = mythic.name;
if (!traitName.toLowerCase(Locale.ROOT).startsWith("mythic action")) {
traitName = "Mythic Action: " + traitName;
}
monster.legendaryActions.add(new Trait(traitName, mythic.description));
}
}
monster.lairActionsDescription = getString(rootDict, "lairDescription");
monster.lairActionsEndNote = getString(rootDict, "lairDescriptionEnd");
String fullLairDesc = combineDescriptions(monster.lairActionsDescription, monster.lairActionsEndNote);
if (!fullLairDesc.isEmpty()) {
monster.lairActions.add(0, new Trait("Lair Actions", fullLairDesc));
}
monster.regionalActionsDescription = getString(rootDict, "regionalDescription");
monster.regionalActionsEndNote = getString(rootDict, "regionalDescriptionEnd");
String fullRegionalDesc = combineDescriptions(monster.regionalActionsDescription, monster.regionalActionsEndNote);
if (!fullRegionalDesc.isEmpty()) {
monster.regionalActions.add(0, new Trait("Regional Effects", fullRegionalDesc));
}
addSavingThrows(monster, rootDict);
monster.skills = getSetOfSkills(rootDict);
monster.damageImmunities = getSetOfDamageTypes(rootDict, "damageTypes", "i");
@@ -104,6 +142,17 @@ public class TetraCubeMonsterImporter implements EntityImporter<Monster> {
return monster;
}
@NonNull
private static String combineDescriptions(String desc1, String desc2) {
if (!desc1.isEmpty() && !desc2.isEmpty()) {
return desc1 + "\n\n" + desc2;
} else if (!desc1.isEmpty()) {
return desc1;
} else {
return desc2;
}
}
private static String getString(JsonObject dict, String name) {
return getString(dict, name, "");
}
@@ -169,7 +218,11 @@ public class TetraCubeMonsterImporter implements EntityImporter<Monster> {
private static void addSense(Monster monster, JsonObject root, String name) {
int distance = getInt(root, name);
if (distance > 0) {
monster.senses.add(formatDistance(name, distance));
String senseStr = formatDistance(name, distance);
if ("blindsight".equals(name) && getBool(root, "blind")) {
senseStr += " (blind beyond this radius)";
}
monster.senses.add(senseStr);
}
}

View File

@@ -206,6 +206,33 @@ public class Monster {
@ColumnInfo(name = "regional_actions", defaultValue = "[]")
public List<Trait> regionalActions;
@ColumnInfo(name = "source_url", defaultValue = "")
public String sourceUrl;
@ColumnInfo(name = "bonus_actions", defaultValue = "[]")
public List<Trait> bonusActions;
@ColumnInfo(name = "mythic_actions", defaultValue = "[]")
public List<Trait> mythicActions;
@ColumnInfo(name = "legendary_actions_description", defaultValue = "")
public String legendaryActionsDescription;
@ColumnInfo(name = "lair_actions_description", defaultValue = "")
public String lairActionsDescription;
@ColumnInfo(name = "lair_actions_end_note", defaultValue = "")
public String lairActionsEndNote;
@ColumnInfo(name = "regional_actions_description", defaultValue = "")
public String regionalActionsDescription;
@ColumnInfo(name = "regional_actions_end_note", defaultValue = "")
public String regionalActionsEndNote;
@ColumnInfo(name = "mythic_actions_description", defaultValue = "")
public String mythicActionsDescription;
public Monster() {
id = UUID.randomUUID();
name = "";
@@ -266,6 +293,15 @@ public class Monster {
lairActions = new ArrayList<>();
legendaryActions = new ArrayList<>();
regionalActions = new ArrayList<>();
bonusActions = new ArrayList<>();
mythicActions = new ArrayList<>();
sourceUrl = "";
legendaryActionsDescription = "";
lairActionsDescription = "";
lairActionsEndNote = "";
regionalActionsDescription = "";
regionalActionsEndNote = "";
mythicActionsDescription = "";
}
public String getMeta() {
@@ -783,6 +819,22 @@ public class Monster {
return actionDescriptions;
}
public List<String> getBonusActionDescriptions() {
ArrayList<String> actionDescriptions = new ArrayList<>();
for (Trait action : bonusActions) {
actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
}
return actionDescriptions;
}
public List<String> getMythicActionDescriptions() {
ArrayList<String> actionDescriptions = new ArrayList<>();
for (Trait action : mythicActions) {
actionDescriptions.add(getPlaceholderReplacedText(String.format("__%s__ %s", action.name, action.description)));
}
return actionDescriptions;
}
public List<String> getReactionDescriptions() {
ArrayList<String> actionDescriptions = new ArrayList<>();
for (Trait action : reactions) {