mirror of
https://github.com/MewoLab/AquaDX.git
synced 2026-09-30 18:58:04 +03:00
[chu3] X-VERSE & LINKED VERSE (#204)
This commit is contained in:
@@ -48,6 +48,11 @@ class AquaGameOptions(
|
||||
|
||||
@SettingField("chu3-matching")
|
||||
var chusanMatchingReflector: String = "",
|
||||
|
||||
@SettingField("chu3-linked-verse")
|
||||
var chusanLvUnlockAll: Boolean = false,
|
||||
@SettingField("chu3-linked-verse")
|
||||
var chusanLvDifficulty: Int = 1,
|
||||
|
||||
@SettingField("chu3-matching-chat")
|
||||
var chusanSymbolChat1: Int? = null,
|
||||
|
||||
@@ -41,6 +41,7 @@ class Chusan(
|
||||
"trophyIdSub2" to { u, v -> u.trophyIdSub2 = v.int },
|
||||
"mapIconId" to { u, v -> u.mapIconId = v.int },
|
||||
"voiceId" to { u, v -> u.voiceId = v.int },
|
||||
"stageId" to { u, v -> u.stageId = v.int },
|
||||
"characterId" to { u, v -> u.characterId = v.int },
|
||||
"avatarWear" to { u, v -> u.avatarWear = v.int },
|
||||
"avatarHead" to { u, v -> u.avatarHead = v.int },
|
||||
|
||||
@@ -13,16 +13,16 @@ class ChusanVersionHelper(val db: Chu3Repos) {
|
||||
val cache: MutableMap<String, String> = mutableMapOf()
|
||||
|
||||
// Obtain the cabinet's most recent version
|
||||
operator fun get(clientId: String): String {
|
||||
fun get(clientId: String): String? {
|
||||
// Try to find the version in the cache
|
||||
cache[clientId]?.let { return it }
|
||||
|
||||
// Not found, check the most recent user
|
||||
return db.userData.findTopByLastClientIdOrderByLastPlayDateDesc(clientId)?.lastDataVersion
|
||||
?.also { cache[clientId] = it } ?: "2.25.13".also { log.warn("No version found for $clientId") }
|
||||
?.also { cache[clientId] = it }
|
||||
}
|
||||
|
||||
operator fun set(clientId: String, version: String) {
|
||||
fun set(clientId: String, version: String) {
|
||||
cache[clientId] = version
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserItem
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserMusicDetail
|
||||
import icu.samnyan.aqua.sega.general.model.CardStatus
|
||||
import icu.samnyan.aqua.sega.general.model.UserRecentRating
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -28,13 +29,19 @@ fun ChusanController.chusanInit() {
|
||||
mapOf("type" to type, "length" to 0, "gameRankingList" to lst)
|
||||
}
|
||||
|
||||
// VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE
|
||||
"GetGameCourseLevel" {
|
||||
// gameCourseLevelList: [{courseId: int, startDate: date, endDate: date}]
|
||||
mapOf("length" to 0, "gameCourseLevelList" to listOf(
|
||||
val opts = TokenChecker.getCurrentSession()?.user?.gameOptions
|
||||
val lst = listOf(
|
||||
// Unlock Challenge
|
||||
mapOf("courseId" to 300004, "startDate" to "2019-01-01 00:00:00", "endDate" to "2077-01-01 11:45:14"),
|
||||
mapOf("courseId" to 300009, "startDate" to "2019-01-01 00:00:00", "endDate" to "2077-01-01 11:45:14")
|
||||
))
|
||||
mapOf("courseId" to 300009, "startDate" to "2019-01-01 00:00:00", "endDate" to "2077-01-01 11:45:14"),
|
||||
) + (0..9).toList().map {
|
||||
// Linked Verse
|
||||
mapOf("courseId" to 500000 + (opts?.chusanLvDifficulty ?: 5) + (it * 100), "startDate" to "2019-01-01 00:00:00", "endDate" to "2077-01-01 11:45:14")
|
||||
}
|
||||
|
||||
mapOf("length" to lst.size, "gameCourseLevelList" to lst)
|
||||
}
|
||||
|
||||
"GetGameUCCondition" {
|
||||
@@ -55,6 +62,40 @@ fun ChusanController.chusanInit() {
|
||||
db.userChallenge.findByUser_Card_ExtId(uid)
|
||||
}
|
||||
|
||||
// The implementation here isn't preferable, but it's functional
|
||||
// Condition checks if the user beat a song from a previous stage and unlocks it if so
|
||||
fun getLinkedVerseCampaign(): List<Any> {
|
||||
val opts = TokenChecker.getCurrentSession()?.user?.gameOptions
|
||||
// No other conditions appear to work properly, so the request for the gates is pretty large. Sorry
|
||||
fun getChartConditions(musicId: Int) =
|
||||
if (opts != null && opts.chusanLvUnlockAll) {
|
||||
listOf( mapOf("type" to 3, "conditionId" to 0, "logicalOpe" to 1, "startDate" to "2024-03-08 01:00:00", "endDate" to "2099-12-31 00:00:00") )
|
||||
} else {
|
||||
(0..5).toList().map {
|
||||
mapOf("type" to 26, "conditionId" to (musicId * 100) + it, "logicalOpe" to 2, "startDate" to "2024-03-08 01:00:00", "endDate" to "2099-12-31 00:00:00") }}
|
||||
|
||||
return db.gameLinkedVerse.findAll().map {
|
||||
val lst = getChartConditions(it.musicId)
|
||||
mapOf("linkedVerseId" to it.id + 1, "length" to lst.size, "conditionList" to lst)
|
||||
} + // ORIGIN is always left unlocked by default
|
||||
listOf(mapOf("linkedVerseId" to 10001, "length" to 1, "conditionList" to listOf(
|
||||
mapOf("type" to 3, "conditionId" to 0, "logicalOpe" to 1, "startDate" to "2024-03-08 01:00:00", "endDate" to "2099-12-31 00:00:00")
|
||||
)))
|
||||
}
|
||||
"GetGameLVConditionOpen" {
|
||||
val lst = getLinkedVerseCampaign()
|
||||
mapOf("length" to lst.size, "gameLinkedVerseConditionOpenList" to lst)
|
||||
}
|
||||
"GetGameLVConditionUnlock" {
|
||||
val lst = getLinkedVerseCampaign()
|
||||
mapOf("length" to lst.size, "gameLinkedVerseConditionUnlockList" to lst)
|
||||
}
|
||||
|
||||
"GetUserLV" {
|
||||
val lst = db.userLinkedVerse.findByUser_Card_ExtId(uid)
|
||||
mapOf("length" to lst.size, "userLinkedVerseList" to lst, "userId" to uid)
|
||||
}
|
||||
|
||||
"GetUserRecMusic".paged("userRecMusicList") {
|
||||
// musicId: int, recMusicList: string
|
||||
// musicId cannot be the same with the id in recMusicList
|
||||
@@ -66,14 +107,9 @@ fun ChusanController.chusanInit() {
|
||||
}
|
||||
|
||||
"GetUserRecRating".paged("userRecRatingList") {
|
||||
// ratingMin: int, ratingMax: int, recMusicList: string
|
||||
// This doesn't work
|
||||
// listOf(
|
||||
// mapOf("ratingMin" to 0, "ratingMax" to 30, "recMusicList" to "2387,1;2658,1")
|
||||
// )
|
||||
// Unimplemented for now
|
||||
empty
|
||||
}
|
||||
// VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE VERSE
|
||||
|
||||
// Stub handlers
|
||||
"GetGameIdlist" { """{"type":"${data["type"]}","length":"0","gameIdlistList":[]}""" }
|
||||
@@ -277,12 +313,16 @@ fun ChusanController.chusanInit() {
|
||||
"GetUserTeam" {
|
||||
val playDate = parsing { data["playDate"] as String }
|
||||
val team = db.userData.findByCard_ExtId(uid)?.card?.aquaUser?.gameOptions?.chusanTeamName?.some
|
||||
?: props.teamName?.some ?: "一緒に歌おう!"
|
||||
?: props.teamName?.some
|
||||
|
||||
mapOf(
|
||||
"userId" to uid, "teamId" to 1, "teamRank" to 1, "teamName" to team,
|
||||
"userTeamPoint" to mapOf("userId" to uid, "teamId" to 1, "orderId" to 1, "teamPoint" to 1, "aggrDate" to playDate)
|
||||
)
|
||||
if (team.isNullOrEmpty())
|
||||
mapOf("userId" to uid, "teamId" to 0)
|
||||
else
|
||||
// TODO: true team implementation
|
||||
mapOf(
|
||||
"userId" to uid, "teamId" to 1, "teamRank" to 1, "teamName" to team,
|
||||
"userTeamPoint" to mapOf("userId" to uid, "teamId" to 1, "orderId" to 1, "teamPoint" to 1, "aggrDate" to playDate)
|
||||
)
|
||||
}
|
||||
|
||||
"GetUserRegion" {
|
||||
@@ -313,7 +353,7 @@ fun ChusanController.chusanInit() {
|
||||
mapOf(
|
||||
"gameSetting" to mapOf(
|
||||
"romVersion" to "$version.00",
|
||||
"dataVersion" to versionHelper[data["clientId"].toString()],
|
||||
"dataVersion" to (versionHelper.get(data["clientId"].toString()) ?: "$version.01"),
|
||||
"isMaintenance" to false,
|
||||
"requestInterval" to 0,
|
||||
"rebootStartTime" to now.minusHours(4).format(fmt),
|
||||
@@ -322,8 +362,6 @@ fun ChusanController.chusanInit() {
|
||||
"maxCountCharacter" to 300,
|
||||
"maxCountItem" to 300,
|
||||
"maxCountMusic" to 300,
|
||||
// "matchStartTime" to now.minusHours(1).format(fmt),
|
||||
// "matchEndTime" to now.plusHours(7).format(fmt),
|
||||
"matchStartTime" to now.withHour(0).withMinute(1).withSecond(0).format(fmt),
|
||||
"matchEndTime" to now.withHour(23).withMinute(59).withSecond(0).format(fmt),
|
||||
"matchTimeLimit" to 10,
|
||||
|
||||
@@ -6,6 +6,7 @@ import icu.samnyan.aqua.sega.chusan.model.request.Chu3UserAll
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.*
|
||||
import icu.samnyan.aqua.sega.general.model.CardStatus
|
||||
import icu.samnyan.aqua.sega.general.model.UserRecentRating
|
||||
import kotlinx.serialization.encodeToString
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun ChusanController.upsertApiInit() {
|
||||
@@ -55,7 +56,7 @@ fun ChusanController.upsertApiInit() {
|
||||
db.userRegions.save(region)
|
||||
}
|
||||
|
||||
versionHelper[u.lastClientId] = u.lastDataVersion
|
||||
versionHelper.set(u.lastClientId, u.lastDataVersion)
|
||||
|
||||
// Set users
|
||||
listOfNotNull(
|
||||
@@ -159,6 +160,13 @@ fun ChusanController.upsertApiInit() {
|
||||
db.userChallenge.saveAll(list.distinctBy { it.unlockChallengeId }.mapApply {
|
||||
id = db.userChallenge.findByUserAndUnlockChallengeId(u, unlockChallengeId)?.id ?: 0 }) }
|
||||
|
||||
userLinkedVerseList?.let { list ->
|
||||
db.userLinkedVerse.saveAll(list.map{
|
||||
it.apply{ it.user = u }
|
||||
}.distinctBy { it.linkedVerseId }.mapApply {
|
||||
id = db.userLinkedVerse.findByUserAndLinkedVerseId(u, linkedVerseId)?.id ?: 0 })
|
||||
}
|
||||
|
||||
// Need testing
|
||||
// userLoginBonusList?.let { list ->
|
||||
// db.userLoginBonus.saveAll(list.distinctBy { it["presetId"] as String }.map {
|
||||
|
||||
@@ -91,4 +91,13 @@ class GameLoginBonusPreset : IdExposedEntity() {
|
||||
var version = 0
|
||||
var presetName: String? = null
|
||||
var isEnabled = false
|
||||
}
|
||||
|
||||
@Entity(name = "ChusanGameLinkedVerse")
|
||||
@Table(name = "chusan_game_linked_verse")
|
||||
class GameLinkedVerse: IdExposedEntity() {
|
||||
var musicId = 0
|
||||
var name: String? = null
|
||||
var startDate: LocalDateTime? = null
|
||||
var endDate: LocalDateTime? = null
|
||||
}
|
||||
@@ -68,6 +68,13 @@ interface Chu3UserCourseRepo : Chu3UserLinked<UserCourse> {
|
||||
fun findByUserAndCourseId(user: Chu3UserData, courseId: Int): UserCourse?
|
||||
}
|
||||
|
||||
interface Chu3UserLinkedVerseRepo : Chu3UserLinked<Chu3UserLinkedVerse> {
|
||||
fun findAllByUser(user: Chu3UserData): List<Chu3UserLinkedVerse?>
|
||||
fun findByUserAndLinkedVerseId(user: Chu3UserData, linkedVerseId: Int): Chu3UserLinkedVerse?
|
||||
}
|
||||
|
||||
interface Chu3GameLinkedVerseRepo : JpaRepository<GameLinkedVerse, Int>
|
||||
|
||||
interface Chu3UserDataRepo : GenericUserDataRepo<Chu3UserData> {
|
||||
fun findTopByLastClientIdOrderByLastPlayDateDesc(lastClientId: String): Chu3UserData?
|
||||
}
|
||||
@@ -201,10 +208,12 @@ class Chu3Repos(
|
||||
val netBattleLog: Chu3NetBattleLogRepo,
|
||||
val userMisc: Chu3UserMiscRepo,
|
||||
val userChallenge: Chu3UserChallengeRepo,
|
||||
val userLinkedVerse: Chu3UserLinkedVerseRepo,
|
||||
val gameCharge: Chu3GameChargeRepo,
|
||||
val gameEvent: Chu3GameEventRepo,
|
||||
val gameGachaCard: Chu3GameGachaCardRepo,
|
||||
val gameGacha: Chu3GameGachaRepo,
|
||||
val gameLoginBonusPresets: Chu3GameLoginBonusPresetsRepo,
|
||||
val gameLoginBonus: Chu3GameLoginBonusRepo
|
||||
val gameLoginBonus: Chu3GameLoginBonusRepo,
|
||||
val gameLinkedVerse: Chu3GameLinkedVerseRepo
|
||||
)
|
||||
@@ -64,4 +64,5 @@ class Chu3UserAll(
|
||||
var userCMissionList: List<UserCMissionResp>? = null,
|
||||
var userFavoriteMusicList: List<FavNewMusic>? = null,
|
||||
var userUnlockChallengeList: List<Chu3UserChallenge>? = null,
|
||||
var userLinkedVerseList: List<Chu3UserLinkedVerse>? = null
|
||||
)
|
||||
|
||||
@@ -116,6 +116,7 @@ class Chu3UserData : BaseEntity(), IUserData {
|
||||
var netBattleConsecutiveWinCount = 0
|
||||
var charaIllustId = 0
|
||||
var skillId = 0
|
||||
var stageId = 0
|
||||
var overPowerPoint = 0
|
||||
var overPowerRate = 0
|
||||
var overPowerLowerRank = 0
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package icu.samnyan.aqua.sega.chusan.model.userdata
|
||||
|
||||
import jakarta.persistence.Entity
|
||||
import jakarta.persistence.Table
|
||||
import jakarta.persistence.UniqueConstraint
|
||||
import java.time.LocalDateTime
|
||||
|
||||
|
||||
@Entity(name = "ChusanUserLinkedVerse")
|
||||
@Table(name = "chusan_user_linked_verse", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "linked_verse_id"])])
|
||||
class Chu3UserLinkedVerse : Chu3UserEntity() {
|
||||
var linkedVerseId = 0
|
||||
var clearCourseId = 0
|
||||
var clearCourseLevel = 0
|
||||
var clearDate: LocalDateTime = LocalDateTime.now()
|
||||
var clearUserId1: Long = 0
|
||||
var clearUserId2: Long = 0
|
||||
var clearUserId3: Long = 0
|
||||
var clearUserName0 = ""
|
||||
var clearUserName1 = ""
|
||||
var clearUserName2 = ""
|
||||
var clearUserName3 = ""
|
||||
var isFirstClear = false
|
||||
var numClear = 0
|
||||
var statusOpen = 0
|
||||
var statusUnlock = 0
|
||||
var progress: String = ""
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE chusan_user_data
|
||||
ADD stage_id INT NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,53 @@
|
||||
ALTER TABLE aqua_game_options
|
||||
ADD chusan_lv_difficulty INT NOT NULL DEFAULT 5;
|
||||
ALTER TABLE aqua_game_options
|
||||
ADD chusan_lv_unlock_all BOOLEAN DEFAULT FALSE;
|
||||
|
||||
CREATE TABLE chusan_game_linked_verse (
|
||||
id BIGINT auto_increment PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
start_date DATETIME NOT NULL,
|
||||
end_date DATETIME NOT NULL,
|
||||
music_id INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE chusan_user_linked_verse
|
||||
(
|
||||
id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
||||
progress VARCHAR(64),
|
||||
user_id BIGINT NOT NULL,
|
||||
linked_verse_id INTEGER NOT NULL,
|
||||
clear_course_id INTEGER NOT NULL,
|
||||
clear_course_level INTEGER NOT NULL,
|
||||
clear_date DATETIME NOT NULL,
|
||||
clear_user_id1 BIGINT NOT NULL,
|
||||
clear_user_id2 BIGINT NOT NULL,
|
||||
clear_user_id3 BIGINT NOT NULL,
|
||||
clear_user_name0 VARCHAR(8) NOT NULL,
|
||||
clear_user_name1 VARCHAR(8) NOT NULL,
|
||||
clear_user_name2 VARCHAR(8) NOT NULL,
|
||||
clear_user_name3 VARCHAR(8) NOT NULL,
|
||||
is_first_clear BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
num_clear INTEGER NOT NULL,
|
||||
status_open INTEGER NOT NULL,
|
||||
status_unlock INTEGER NOT NULL,
|
||||
CONSTRAINT fku_chusan_user_linked_verse FOREIGN KEY (user_id) REFERENCES chusan_user_data (id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT unique_user_linked_verse UNIQUE (user_id, linked_verse_id)
|
||||
);
|
||||
|
||||
ALTER TABLE chusan_user_playlog
|
||||
MODIFY COLUMN played_user_id1 BIGINT;
|
||||
ALTER TABLE chusan_user_playlog
|
||||
MODIFY COLUMN played_user_id2 BIGINT;
|
||||
ALTER TABLE chusan_user_playlog
|
||||
MODIFY COLUMN played_user_id3 BIGINT;
|
||||
|
||||
INSERT INTO chusan_game_linked_verse (id, name, start_date, end_date, music_id)
|
||||
VALUES
|
||||
(10001, 'Linked GATE ORIGIN', '2019-01-01 00:00:00.000000', '2029-01-01 00:00:00.000000',2838),
|
||||
(10002, 'Linked GATE AIR', '2019-01-01 00:00:00.000000', '2029-01-01 00:00:00.000000',2846),
|
||||
(10003, 'Linked GATE STAR', '2019-01-01 00:00:00.000000', '2029-01-01 00:00:00.000000',2858),
|
||||
(10004, 'Linked GATE AMAZON', '2019-01-01 00:00:00.000000', '2029-01-01 00:00:00.000000',2869),
|
||||
(10005, 'Linked GATE CRYSTAL', '2019-01-01 00:00:00.000000', '2029-01-01 00:00:00.000000',2880),
|
||||
(10006, 'Linked GATE PARADISE', '2019-01-01 00:00:00.000000', '2029-01-01 00:00:00.000000',2891),
|
||||
(10007, 'Linked GATE NEW', '2019-01-01 00:00:00.000000', '2029-01-01 00:00:00.000000',2919);
|
||||
Reference in New Issue
Block a user