diff --git a/app/src/main/java/com/droiddeck/launcher/runtime/BattleNet.kt b/app/src/main/java/com/droiddeck/launcher/runtime/BattleNet.kt index fa58c26ea..a98e3d0cf 100644 --- a/app/src/main/java/com/droiddeck/launcher/runtime/BattleNet.kt +++ b/app/src/main/java/com/droiddeck/launcher/runtime/BattleNet.kt @@ -61,6 +61,9 @@ object BattleNet { val STORE: List get() = TITLES.distinctBy { it.code }.filter { it.uid != "d3cn" && it.code != "WoWC" && it.code != "WoWF" } + // Blizzard's China client installs some products under a CN uid; they are the same games and keep their store identity. + private val CN_UIDS = mapOf("s2_cn" to "s2", "osic" to "osi", "anbs_cn" to "anbs") + fun notInstalled(title: Title, installedIds: Collection<String?>) = installedIds.mapNotNull { id -> id?.let(::title)?.code }.none { it == title.code } @@ -164,8 +167,10 @@ object BattleNet { internal fun title(uid: String): Title? { val id = uid.lowercase() TITLES.firstOrNull { it.uid == id }?.let { return it } + CN_UIDS[id]?.let { alias -> TITLES.firstOrNull { it.uid == alias }?.let { return it } } val base = id.substringBeforeLast('_', "") - return if (base.isNotEmpty() && id.substringAfterLast('_') in LOCALES) TITLES.firstOrNull { it.uid == base } else null + if (base.isEmpty() || id.substringAfterLast('_') !in LOCALES) return null + return TITLES.firstOrNull { it.uid == base } ?: CN_UIDS[base]?.let { alias -> TITLES.firstOrNull { it.uid == alias } } } internal fun titleForProduct(product: String): Title? { diff --git a/app/src/test/java/com/droiddeck/launcher/runtime/BattleNetTest.kt b/app/src/test/java/com/droiddeck/launcher/runtime/BattleNetTest.kt index 77800dc1e..c3d821d07 100644 --- a/app/src/test/java/com/droiddeck/launcher/runtime/BattleNetTest.kt +++ b/app/src/test/java/com/droiddeck/launcher/runtime/BattleNetTest.kt @@ -259,6 +259,7 @@ class BattleNetTest { BattleNet.hostFolder(context, "Z:/root/Games/Stores/Battle.net/Hearthstone/")) } + @Test fun wowForeverIsListedBesideRetailInTheSharedWorldOfWarcraftFolder() { val pfx = File(BattleNet.prefix(context), "pfx").apply { mkdirs() } val wow = File(pfx, "drive_c/Program Files (x86)/World of Warcraft").apply { mkdirs() } @@ -329,6 +330,24 @@ class BattleNetTest { assertEquals(listOf(File(wow, "_forever_")), BattleNet.games(context).map { it.folder }) db.writeBytes(message(forever, retail)) assertEquals(listOf(File(wow, "_forever_"), wow), BattleNet.games(context).map { it.folder }) + + @Test fun aGameInstalledUnderBlizzardsChineseUidIsStillListed() { + val pfx = File(BattleNet.prefix(context), "pfx").apply { mkdirs() } + File(pfx, "drive_c/ProgramData/Battle.net/Agent").mkdirs() + File(pfx, "drive_c/ProgramData/Battle.net/Agent/product.db").writeBytes(message( + field(1, message(field(1, "osic"), field(3, message(field(1, "Z:/root/Games/Stores/Battle.net/Diablo II Resurrected"))))), + field(1, message(field(1, "s2_cn"), field(3, message(field(1, "Z:/root/Games/Stores/Battle.net/StarCraft II"))))), + )) + for (folder in listOf("Diablo II Resurrected", "StarCraft II")) { + File(LinuxRuntime.rootDir(context), "root/Games/Stores/Battle.net/$folder").mkdirs() + } + val games = BattleNet.games(context) + assertEquals(listOf("osic", "s2_cn"), games.map { it.installUid }) + assertEquals(listOf("osi", "s2"), games.map { it.uid }) + assertEquals(listOf("Diablo II: Resurrected" to "OSI", "StarCraft II" to "S2"), games.map { it.name to it.code }) + assertFalse(BattleNet.notInstalled(BattleNet.title("osi")!!, listOf("osic"))) + assertFalse(BattleNet.notInstalled(BattleNet.title("s2")!!, games.map { it.installUid })) + } @Test fun aGamesShortcutHasBattleNetLaunchItInItsPrefix() {