diff --git a/src/main/kotlin/net/taehui/twilight/BMSONCompiler.kt b/src/main/kotlin/net/taehui/twilight/BMSONCompiler.kt index 2d68576..f7f3fe4 100644 --- a/src/main/kotlin/net/taehui/twilight/BMSONCompiler.kt +++ b/src/main/kotlin/net/taehui/twilight/BMSONCompiler.kt @@ -14,11 +14,11 @@ class BMSONCompiler(noteFileData: ByteArray, format: String) : BaseCompiler(noteFileData, format) { private val bmsonPositionLogicalYMap = TreeMap() private val bmsonPositionBPMMap = TreeMap() - private lateinit var text: JSON.Bmson + private lateinit var text: JSON.BMSON private var res = 0L override fun handleCompile(targetComputing: Computing) { - text = ObjectMapper().readValue(String(noteFileData, Charset.forName(format)), JSON.Bmson::class.java) + text = ObjectMapper().readValue(String(noteFileData, Charset.forName(format)), JSON.BMSON::class.java) val title = text.info.title val titleAssister0 = text.info.subtitle val titleAssister1 = text.info.chart_name diff --git a/src/main/kotlin/net/taehui/twilight/JSON.kt b/src/main/kotlin/net/taehui/twilight/JSON.kt index 54d10b6..498a63a 100644 --- a/src/main/kotlin/net/taehui/twilight/JSON.kt +++ b/src/main/kotlin/net/taehui/twilight/JSON.kt @@ -7,19 +7,18 @@ class JSON { @JsonIgnoreProperties(ignoreUnknown = true) - data class Bmson( + class BMSON( val bga: BGA = BGA(), val bpm_events: List = mutableListOf(), - val info: BmsonInfo = BmsonInfo(), - val lines: List = mutableListOf(), - val mine_channels: List = mutableListOf(), - val sound_channels: List = mutableListOf(), + val info: BMSONInfo = BMSONInfo(), + val lines: List = mutableListOf(), + val mine_channels: List = mutableListOf(), + val sound_channels: List = mutableListOf(), val stop_events: List = mutableListOf() ) { @JsonIgnoreProperties(ignoreUnknown = true) - data class BGA( + class BGA( val bga_events: List = mutableListOf(), - val bga_header: List = mutableListOf(), val layer_events: List = mutableListOf(), val poor_events: List = mutableListOf() ) { @@ -30,13 +29,13 @@ } @JsonIgnoreProperties(ignoreUnknown = true) - data class BPMEvent( + class BPMEvent( val bpm: Double = 0.0, val y: Long = 0L ) @JsonIgnoreProperties(ignoreUnknown = true) - data class BmsonInfo( + class BMSONInfo( val artist: String = "", val chart_name: String = "", val genre: String = "", @@ -53,17 +52,17 @@ ) @JsonIgnoreProperties(ignoreUnknown = true) - data class BarLine( + class Meter( val y: Long = 0L ) @JsonIgnoreProperties(ignoreUnknown = true) - data class SoundChannel( + class AudioChannel( val name: String = "", val notes: List = mutableListOf() ) { @JsonIgnoreProperties(ignoreUnknown = true) - data class Note( + class Note( val damage: Double = 0.0, val l: Long = 0L, val x: Long = 0L, @@ -72,36 +71,37 @@ } @JsonIgnoreProperties(ignoreUnknown = true) - data class StopEvent( + class StopEvent( val duration: Long, val y: Long ) } @JsonIgnoreProperties(ignoreUnknown = true) - data class BMSTable( + class BMSTable( val name: String = "", val symbol: String = "", - val data_url: String = "" + val data_url: String = "", + val level_order: Array = emptyArray() ) @JsonIgnoreProperties(ignoreUnknown = true) - data class BMSTableData( + class BMSTableData( val md5: String = "", val level: String = "", val sha256: String = "", ) @JsonIgnoreProperties(ignoreUnknown = true) - data class N2MT( - val message: Message = Message() + class N2MT( + val message: MSG = MSG() ) { @JsonIgnoreProperties(ignoreUnknown = true) - data class Message( - val result: Result = Result() + class MSG( + val result: Data = Data() ) { @JsonIgnoreProperties(ignoreUnknown = true) - data class Result( + class Data( val translatedText: String = "" ) } diff --git a/src/main/kotlin/net/taehui/twilight/system/AbilitySystem.kt b/src/main/kotlin/net/taehui/twilight/system/AbilitySystem.kt index 275ac58..7a24893 100644 --- a/src/main/kotlin/net/taehui/twilight/system/AbilitySystem.kt +++ b/src/main/kotlin/net/taehui/twilight/system/AbilitySystem.kt @@ -5,7 +5,6 @@ import net.taehui.twilight.Logger import net.taehui.twilight.TwilightComponent import net.taehui.twilight.Utility -import org.apache.commons.io.FileUtils import org.apache.commons.io.FilenameUtils import org.apache.hc.client5.http.classic.methods.HttpGet import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler @@ -13,6 +12,8 @@ import org.jsoup.Jsoup import java.io.IOException import java.nio.file.Files +import java.util.Collections +import java.util.TreeSet object AbilitySystem : Logger { class DefaultAbility { @@ -38,6 +39,7 @@ private val noteIDAbilityMap = arrayOf>(AbilityMap(), AbilityMap(), AbilityMap()) private val noteIDAbilityIDsMap = AbilityMap>() + private val noteIDAbilityNamesMap = AbilityMap>() private val abilityNameAbilityIDsMap = mutableMapOf>() var isLoading = false @@ -109,6 +111,8 @@ noteIDAbilityMap[AbilityClassSystem.AbilityClassVariety.ABILITY_CLASS_5K.ordinal].wipe() noteIDAbilityMap[AbilityClassSystem.AbilityClassVariety.ABILITY_CLASS_7K.ordinal].wipe() noteIDAbilityIDsMap.wipe() + noteIDAbilityNamesMap.wipe() + abilityNameAbilityIDsMap.clear() Files.list(TwilightComponent.ABILITY_ENTRY_PATH).use { abilityFilePaths -> abilityFilePaths.filter { it.fileName.toString().startsWith("#") }.sorted( Comparator.comparingInt { abilityFilePath -> @@ -118,18 +122,23 @@ } ).forEach { abilityFilePath -> val abilityFileName = abilityFilePath.fileName.toString() + val abilityName = FilenameUtils.removeExtension( + abilityFileName.substring(abilityFileName.indexOf('#') + 1) + ) val abilityClassVariety = defaultAbility.abilityFiles.find { it.fileName == abilityFileName }?.abilityClassVariety if (abilityClassVariety != null) { val noteIDAbilityMap = noteIDAbilityMap[abilityClassVariety.ordinal] val abilityTable = jm.readValue(abilityFilePath.toFile(), JSON.BMSTable::class.java) + val levels = + abilityTable.level_order.map { "${abilityTable.symbol}$it" }.toTypedArray(); jm.readValue( TwilightComponent.ABILITY_ENTRY_PATH.resolve(abilityTable.name + ".json") .toFile(), Array::class.java ).forEach { abilityTableData -> - val abilityID = abilityTable.symbol + abilityTableData.level + val abilityID = "${abilityTable.symbol}${abilityTableData.level}" val ability = abilityMap[abilityID] ?: 0.0 if (ability > 0.0) { if (abilityTableData.md5.isNotEmpty()) { @@ -137,20 +146,22 @@ noteIDAbilityIDsMap.hashMap128.computeIfAbsent( abilityTableData.md5 ) { mutableListOf() }.add(abilityID) + noteIDAbilityNamesMap.hashMap128.computeIfAbsent( + abilityTableData.md5 + ) { mutableListOf() }.add(abilityName) } if (abilityTableData.sha256.isNotEmpty()) { noteIDAbilityMap.hashMap256.putIfAbsent(abilityTableData.sha256, ability) - noteIDAbilityIDsMap.hashMap128.computeIfAbsent( + noteIDAbilityIDsMap.hashMap256.computeIfAbsent( abilityTableData.sha256 ) { mutableListOf() }.add(abilityID) + noteIDAbilityNamesMap.hashMap256.computeIfAbsent( + abilityTableData.md5 + ) { mutableListOf() }.add(abilityName) } } - abilityNameAbilityIDsMap.computeIfAbsent( - FilenameUtils.removeExtension( - abilityFileName.substring(abilityFileName.indexOf('#') + 1) - ) - ) { - mutableListOf() + abilityNameAbilityIDsMap.computeIfAbsent(abilityName) { + if (levels.isEmpty()) mutableListOf() else TreeSet { o1, o2 -> levels.indexOf(o1).compareTo(levels.indexOf(o2)) } }.add(abilityID) } logInfo("Loaded Ability (${abilityTable.name})") @@ -191,6 +202,16 @@ ) } + fun getAbilityNames( + noteID128: String, + noteID256: String + ): Collection { + return noteIDAbilityNamesMap.hashMap128.getOrDefault( + noteID128, + noteIDAbilityNamesMap.hashMap256.getOrDefault(noteID256, emptyList()) + ) + } + fun getAbilityIDs( abilityName: String ): Collection { diff --git a/src/main/kotlin/net/taehui/twilight/system/DB.kt b/src/main/kotlin/net/taehui/twilight/system/DB.kt index b75ada3..7d8265f 100644 --- a/src/main/kotlin/net/taehui/twilight/system/DB.kt +++ b/src/main/kotlin/net/taehui/twilight/system/DB.kt @@ -2557,13 +2557,16 @@ fun setLevelID(levelID: String) { val avatarLevelVSItems = mutableSetOf() val targetLevelVSItems = mutableSetOf() - (if (levelID == "*") avatarLevelVSMap.keys.intersect(targetLevelVSMap.keys) else avatarLevelVSMap.filter { - AbilitySystem.getAbilityIDs(it.value.noteID128, it.value.noteID256) - .contains(levelID) + (if (levelName == "*") avatarLevelVSMap.keys.intersect(targetLevelVSMap.keys) else if (levelID == "*") avatarLevelVSMap.filter { + AbilitySystem.getAbilityNames(it.value.noteID128, it.value.noteID256).contains(levelName) }.keys .intersect(targetLevelVSMap.filter { - AbilitySystem.getAbilityIDs(it.value.noteID128, it.value.noteID256) - .contains(levelID) + AbilitySystem.getAbilityNames(it.value.noteID128, it.value.noteID256).contains(levelName) + }.keys) else avatarLevelVSMap.filter { + AbilitySystem.getAbilityIDs(it.value.noteID128, it.value.noteID256).contains(levelID) + }.keys + .intersect(targetLevelVSMap.filter { + AbilitySystem.getAbilityIDs(it.value.noteID128, it.value.noteID256).contains(levelID) }.keys)) .forEach { noteID -> val avatarLevelVSItem = avatarLevelVSMap[noteID]