From b3955731c2af4e6eb78689a90752fd7b5832ff48 Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Mon, 18 Mar 2024 05:31:55 -0400 Subject: [PATCH] [+] Maimai item unlock --- src/main/java/ext/Ext.kt | 11 +++++ .../java/icu/samnyan/aqua/net/games/Models.kt | 18 +++++--- .../handler/impl/GetUserItemHandler.kt | 46 ++++++++++++++----- .../sega/maimai2/model/userdata/UserItem.java | 37 ++++++++++----- .../icu/samnyan/aqua/spring/AquaLogging.kt | 3 +- src/main/resources/meta/update.sh | 1 + 6 files changed, 84 insertions(+), 32 deletions(-) diff --git a/src/main/java/ext/Ext.kt b/src/main/java/ext/Ext.kt index f68001dc..f80b91d5 100644 --- a/src/main/java/ext/Ext.kt +++ b/src/main/java/ext/Ext.kt @@ -12,6 +12,7 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonNamingStrategy import org.apache.tika.Tika import org.apache.tika.mime.MimeTypes +import org.slf4j.LoggerFactory import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestHeader @@ -67,6 +68,16 @@ val HTTP = HttpClient(CIO) { val TIKA = Tika() val MIMES = MimeTypes.getDefaultMimeTypes() +// Class resource +object Ext { + val log = LoggerFactory.getLogger(Ext::class.java) +} +fun res(name: Str) = Ext::class.java.getResourceAsStream(name) +fun resStr(name: Str) = res(name)?.reader()?.readText() +inline fun resJson(name: Str, warn: Boolean = true) = resStr(name)?.let { + JSON.decodeFromString(it) +} ?: run { if (warn) Ext.log.warn("Resource $name is not found"); null } + // Date and time fun millis() = System.currentTimeMillis() val DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd") diff --git a/src/main/java/icu/samnyan/aqua/net/games/Models.kt b/src/main/java/icu/samnyan/aqua/net/games/Models.kt index e1b58737..dfe40174 100644 --- a/src/main/java/icu/samnyan/aqua/net/games/Models.kt +++ b/src/main/java/icu/samnyan/aqua/net/games/Models.kt @@ -68,7 +68,13 @@ data class GenericMusicMeta( @Serializable data class GenericNoteMeta( val lv: Double, - val lvId: Int +) + +@Serializable +data class GenericItemMeta( + val name: String? = null, + val disable: Boolean? = null, + val ver: String? = null ) // Here are some interfaces to generalize across multiple games @@ -111,12 +117,10 @@ interface GenericPlaylogRepo : JpaRepository { } abstract class GameApiController(name: String) { - val musicMapping: Map = GameApiController::class.java - .getResourceAsStream("/meta/$name/music.json") - .use { it?.reader()?.readText() } - ?.let { JSON.decodeFromString>(it) } - ?.mapKeys { it.key.toInt() } - ?: emptyMap() + val musicMapping = resJson>("/meta/$name/music.json") + ?.mapKeys { it.key.toInt() } ?: emptyMap() + + val itemMapping = resJson>>("/meta/$name/items.json") ?: emptyMap() abstract val us: AquaUserServices abstract val userDataRepo: GenericUserDataRepo<*> diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetUserItemHandler.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetUserItemHandler.kt index 20b45bdf..d1ebec3a 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetUserItemHandler.kt +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetUserItemHandler.kt @@ -4,6 +4,7 @@ import icu.samnyan.aqua.net.games.Maimai2 import icu.samnyan.aqua.sega.general.dao.CardRepository import icu.samnyan.aqua.sega.maimai2.handler.BaseHandler import icu.samnyan.aqua.sega.maimai2.model.Mai2Repos +import icu.samnyan.aqua.sega.maimai2.model.userdata.UserItem.Mai2ItemKind import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.data.domain.PageRequest @@ -25,7 +26,21 @@ class GetUserItemHandler( "itemId" to it.key, "stock" to 1, "isValid" to true, - ).toMap() } } + ) } } + + val itemUnlock = Mai2ItemKind.ALL.filter { it.key in 1..3 || it.key in 9..12 } + .mapValues { (kind, kindEnum) -> maimai2.itemMapping[kindEnum.name]?.map { (id, item) -> + mapOf( + "itemKind" to kind, + "itemId" to id, + "stock" to 1, + "isValid" to true, + ) } ?: emptyList() } + + init { + if (musicUnlock[5].isNullOrEmpty()) logger.warn("Mai2 music info is empty") + if (itemUnlock[1].isNullOrEmpty()) logger.warn("Mai2 item info is empty") + } override fun handle(request: Map): Any { val userId = (request["userId"] as Number).toLong() @@ -35,19 +50,28 @@ class GetUserItemHandler( val kind = (nextIndexVal / MULT).toInt() val nextIndex = (nextIndexVal % MULT).toInt() val pageNum = nextIndex / maxCount + val kindType = Mai2ItemKind.ALL[kind]?.name // Aqua Net game unlock feature cardRepo.findByExtId(userId).getOrNull()?.aquaUser?.gameOptions?.let { opt -> - // All Music unlock - if (kind in 5..8 && opt.unlockMusic) { - logger.info("Response: ${maimai2.musicMapping.size} items - Music unlock") - return mapOf( - "userId" to userId, - "nextIndex" to 0, - "itemKind" to kind, - "userItemList" to musicUnlock.getValue(kind) - ) + val items = when { + (kind in 5..8) && opt.unlockMusic -> musicUnlock.getValue(kind) + (kind in 1..3 || kind == 11) && opt.unlockCollectables -> itemUnlock[kind] + (kind == 12) && opt.unlockTickets -> itemUnlock[kind] + (kind in 9..10) && opt.unlockChara -> itemUnlock[kind] + else -> emptyList() } + + // If no items are found, disable the unlock feature + if (items.isNullOrEmpty()) return@let + + logger.info("Response: ${items.size} $kindType items - All unlock") + return mapOf( + "userId" to userId, + "nextIndex" to 0, + "itemKind" to kind, + "userItemList" to items + ) } val dbPage = repos.userItem.findByUser_Card_ExtIdAndItemKind(userId, kind, PageRequest.of(pageNum, maxCount)) @@ -60,7 +84,7 @@ class GetUserItemHandler( "userItemList" to dbPage.content ) - logger.info("Response: ${dbPage.numberOfElements} items") + logger.info("Response: ${dbPage.numberOfElements} $kindType items") return result } diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserItem.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserItem.java index d2fcd9d0..70a6372e 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserItem.java +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserItem.java @@ -1,13 +1,15 @@ package icu.samnyan.aqua.sega.maimai2.model.userdata; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import jakarta.persistence.*; @@ -40,15 +42,26 @@ public class UserItem implements Serializable { this.user = user; } - public static final int KIND_NAMEPLATE = 1; - public static final int KIND_TITLE = 2; - public static final int KIND_ICON = 3; - public static final int KIND_MUSIC_UNLOCK = 5; - public static final int KIND_MUSIC_MASTER_UNLOCK = 6; - public static final int KIND_MUSIC_REMASTER_UNLOCK = 7; - public static final int KIND_MUSIC_STRONG_UNLOCK = 8; - public static final int KIND_CHARACTER = 9; - public static final int KIND_PARTNER = 10; - public static final int KIND_FRAME = 11; - public static final int KIND_TICKETS = 12; + public enum Mai2ItemKind { + plate(1), + title(2), + icon(3), + musicUnlock(5), + musicMasterUnlock(6), + musicRemasterUnlock(7), + musicStrongUnlock(8), + chara(9), + partner(10), + frame(11), + ticket(12); + + public final int value; + + Mai2ItemKind(int value) { + this.value = value; + } + + public static final Map ALL = Arrays.stream(Mai2ItemKind.class.getEnumConstants()) + .map(k -> Map.entry(k.value, k)).collect(HashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), Map::putAll); + } } diff --git a/src/main/java/icu/samnyan/aqua/spring/AquaLogging.kt b/src/main/java/icu/samnyan/aqua/spring/AquaLogging.kt index 6802afc7..b540c79d 100644 --- a/src/main/java/icu/samnyan/aqua/spring/AquaLogging.kt +++ b/src/main/java/icu/samnyan/aqua/spring/AquaLogging.kt @@ -2,7 +2,6 @@ package icu.samnyan.aqua.spring import ch.qos.logback.classic.spi.ILoggingEvent import ch.qos.logback.core.pattern.CompositeConverter -import ext.center import ext.get import org.springframework.boot.ansi.AnsiColor import org.springframework.boot.ansi.AnsiOutput @@ -10,7 +9,7 @@ import org.springframework.boot.ansi.AnsiOutput private const val PROJECT_PACKAGE_PREFIX = "icu.samnyan.aqua" private const val SEGA_PACKAGE_PREFIX = "icu.samnyan.aqua.sega" private val SYSTEM_COLOR = AnsiColor.WHITE -private val SEGA_COLOR = AnsiColor.MAGENTA +private val SEGA_COLOR = AnsiColor.BRIGHT_CYAN private val MISC_COLOR = AnsiColor.BRIGHT_BLUE class LoggerComponent : CompositeConverter() { diff --git a/src/main/resources/meta/update.sh b/src/main/resources/meta/update.sh index 28cb8163..f3667605 100644 --- a/src/main/resources/meta/update.sh +++ b/src/main/resources/meta/update.sh @@ -7,4 +7,5 @@ mkdir -p "$DIR/ongeki" "$DIR/mai2" "$DIR/chu3" curl "https://aquadx.net/d/ongeki/00/all-music.json" -o "$DIR/ongeki/music.json" curl "https://aquadx.net/d/mai2/00/all-music.json" -o "$DIR/mai2/music.json" +curl "https://aquadx.net/d/mai2/00/all-items.json" -o "$DIR/mai2/items.json" curl "https://aquadx.net/d/chu3/00/all-music.json" -o "$DIR/chu3/music.json"