mirror of
https://github.com/Walter-Sparrow/lunar-tear.git
synced 2026-07-02 05:43:41 +03:00
Implement world-map entities
Build and Push Docker images to Docker Hub / build-and-push (push) Has been cancelled
Build and Push Docker images to Docker Hub / build-and-push (push) Has been cancelled
This commit is contained in:
@@ -2,11 +2,21 @@ package userdata
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"lunar-tear/server/internal/masterdata"
|
||||
"lunar-tear/server/internal/store"
|
||||
"lunar-tear/server/internal/utils"
|
||||
)
|
||||
|
||||
var gimmickOrnamentRefs = sync.OnceValue(masterdata.LoadGimmickOrnamentRefs)
|
||||
var gimmickSequenceChains = sync.OnceValue(masterdata.LoadGimmickSequenceChains)
|
||||
var hiddenSequenceSet = sync.OnceValue(masterdata.LoadHiddenGimmickSequenceIDs)
|
||||
var gimmickSequenceRanks = sync.OnceValue(masterdata.LoadGimmickSequenceRanks)
|
||||
var birdGimmicks = sync.OnceValue(masterdata.LoadBirdGimmickIDs)
|
||||
|
||||
const birdDefaultBaseDatetime int64 = 1577836800000 // 2020-01-01 00:00:00 UTC in ms
|
||||
|
||||
func init() {
|
||||
register("IUserGimmick", func(user store.UserState) string {
|
||||
s, _ := utils.EncodeJSONMaps(sortedGimmickRecords(user)...)
|
||||
@@ -26,9 +36,65 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
func projectActiveChainOrnaments(
|
||||
user store.UserState,
|
||||
addKey func(seqKey store.GimmickSequenceKey, seqId int32, ref masterdata.GimmickOrnamentRef),
|
||||
sizeFn func() int,
|
||||
cap int,
|
||||
) {
|
||||
refs := gimmickOrnamentRefs()
|
||||
chains := gimmickSequenceChains()
|
||||
hiddenSeq := hiddenSequenceSet()
|
||||
|
||||
walkChain := func(seqKey store.GimmickSequenceKey) {
|
||||
chain := chains[seqKey.GimmickSequenceId]
|
||||
if len(chain) == 0 {
|
||||
chain = []int32{seqKey.GimmickSequenceId}
|
||||
}
|
||||
for _, seqId := range chain {
|
||||
for _, ref := range refs[seqId] {
|
||||
addKey(seqKey, seqId, ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var nonHidden []store.GimmickSequenceKey
|
||||
for seqKey := range user.Gimmick.Sequences {
|
||||
if hiddenSeq[seqKey.GimmickSequenceId] {
|
||||
walkChain(seqKey)
|
||||
} else {
|
||||
nonHidden = append(nonHidden, seqKey)
|
||||
}
|
||||
}
|
||||
for _, seqKey := range nonHidden {
|
||||
if sizeFn() >= cap {
|
||||
break
|
||||
}
|
||||
walkChain(seqKey)
|
||||
}
|
||||
}
|
||||
|
||||
func sortedGimmickRecords(user store.UserState) []map[string]any {
|
||||
keys := make([]store.GimmickKey, 0, len(user.Gimmick.Progress))
|
||||
|
||||
keySet := make(map[store.GimmickKey]struct{})
|
||||
// Real progress rows (genuine user data) — always kept.
|
||||
for key := range user.Gimmick.Progress {
|
||||
keySet[key] = struct{}{}
|
||||
}
|
||||
projectActiveChainOrnaments(user,
|
||||
func(seqKey store.GimmickSequenceKey, seqId int32, ref masterdata.GimmickOrnamentRef) {
|
||||
keySet[store.GimmickKey{
|
||||
GimmickSequenceScheduleId: seqKey.GimmickSequenceScheduleId,
|
||||
GimmickSequenceId: seqId,
|
||||
GimmickId: ref.GimmickId,
|
||||
}] = struct{}{}
|
||||
},
|
||||
func() int { return len(keySet) },
|
||||
masterdata.MaxUserGimmickRows,
|
||||
)
|
||||
|
||||
keys := make([]store.GimmickKey, 0, len(keySet))
|
||||
for key := range keySet {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
@@ -37,57 +103,103 @@ func sortedGimmickRecords(user store.UserState) []map[string]any {
|
||||
|
||||
records := make([]map[string]any, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
row := user.Gimmick.Progress[key]
|
||||
isGimmickCleared := false
|
||||
startDatetime := user.GameStartDatetime
|
||||
latestVersion := user.GameStartDatetime
|
||||
if row, ok := user.Gimmick.Progress[key]; ok {
|
||||
isGimmickCleared = row.IsGimmickCleared
|
||||
startDatetime = row.StartDatetime
|
||||
latestVersion = row.LatestVersion
|
||||
}
|
||||
records = append(records, map[string]any{
|
||||
"userId": user.UserId,
|
||||
"gimmickSequenceScheduleId": row.Key.GimmickSequenceScheduleId,
|
||||
"gimmickSequenceId": row.Key.GimmickSequenceId,
|
||||
"gimmickId": row.Key.GimmickId,
|
||||
"isGimmickCleared": row.IsGimmickCleared,
|
||||
"startDatetime": row.StartDatetime,
|
||||
"latestVersion": row.LatestVersion,
|
||||
"gimmickSequenceScheduleId": key.GimmickSequenceScheduleId,
|
||||
"gimmickSequenceId": key.GimmickSequenceId,
|
||||
"gimmickId": key.GimmickId,
|
||||
"isGimmickCleared": isGimmickCleared,
|
||||
"startDatetime": startDatetime,
|
||||
"latestVersion": latestVersion,
|
||||
})
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
||||
func sortedGimmickOrnamentProgressRecords(user store.UserState) []map[string]any {
|
||||
keys := make([]store.GimmickOrnamentKey, 0, len(user.Gimmick.OrnamentProgress))
|
||||
|
||||
keySet := make(map[store.GimmickOrnamentKey]struct{})
|
||||
// Real progress rows (genuine user data) — always kept.
|
||||
for key := range user.Gimmick.OrnamentProgress {
|
||||
keySet[key] = struct{}{}
|
||||
}
|
||||
projectActiveChainOrnaments(user,
|
||||
func(seqKey store.GimmickSequenceKey, seqId int32, ref masterdata.GimmickOrnamentRef) {
|
||||
keySet[store.GimmickOrnamentKey{
|
||||
GimmickSequenceScheduleId: seqKey.GimmickSequenceScheduleId,
|
||||
GimmickSequenceId: seqId,
|
||||
GimmickId: ref.GimmickId,
|
||||
GimmickOrnamentIndex: ref.OrnamentIndex,
|
||||
}] = struct{}{}
|
||||
},
|
||||
func() int { return len(keySet) },
|
||||
masterdata.MaxUserGimmickRows,
|
||||
)
|
||||
|
||||
keys := make([]store.GimmickOrnamentKey, 0, len(keySet))
|
||||
for key := range keySet {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return compareGimmickOrnamentKey(keys[i], keys[j]) < 0
|
||||
})
|
||||
|
||||
birdG := birdGimmicks()
|
||||
records := make([]map[string]any, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
row := user.Gimmick.OrnamentProgress[key]
|
||||
progressValueBit := int32(0)
|
||||
baseDatetime := user.GameStartDatetime
|
||||
latestVersion := user.GameStartDatetime
|
||||
if row, ok := user.Gimmick.OrnamentProgress[key]; ok {
|
||||
progressValueBit = row.ProgressValueBit
|
||||
baseDatetime = row.BaseDatetime
|
||||
latestVersion = row.LatestVersion
|
||||
} else if birdG[key.GimmickId] {
|
||||
baseDatetime = birdDefaultBaseDatetime
|
||||
}
|
||||
records = append(records, map[string]any{
|
||||
"userId": user.UserId,
|
||||
"gimmickSequenceScheduleId": row.Key.GimmickSequenceScheduleId,
|
||||
"gimmickSequenceId": row.Key.GimmickSequenceId,
|
||||
"gimmickId": row.Key.GimmickId,
|
||||
"gimmickOrnamentIndex": row.Key.GimmickOrnamentIndex,
|
||||
"progressValueBit": row.ProgressValueBit,
|
||||
"baseDatetime": row.BaseDatetime,
|
||||
"latestVersion": row.LatestVersion,
|
||||
"gimmickSequenceScheduleId": key.GimmickSequenceScheduleId,
|
||||
"gimmickSequenceId": key.GimmickSequenceId,
|
||||
"gimmickId": key.GimmickId,
|
||||
"gimmickOrnamentIndex": key.GimmickOrnamentIndex,
|
||||
"progressValueBit": progressValueBit,
|
||||
"baseDatetime": baseDatetime,
|
||||
"latestVersion": latestVersion,
|
||||
})
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
||||
func sortedGimmickSequenceRecords(user store.UserState) []map[string]any {
|
||||
|
||||
ranks := gimmickSequenceRanks()
|
||||
|
||||
keys := make([]store.GimmickSequenceKey, 0, len(user.Gimmick.Sequences))
|
||||
for key := range user.Gimmick.Sequences {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
ri, rj := ranks[keys[i].GimmickSequenceId], ranks[keys[j].GimmickSequenceId]
|
||||
if ri != rj {
|
||||
return ri < rj
|
||||
}
|
||||
if keys[i].GimmickSequenceScheduleId != keys[j].GimmickSequenceScheduleId {
|
||||
return keys[i].GimmickSequenceScheduleId < keys[j].GimmickSequenceScheduleId
|
||||
}
|
||||
return keys[i].GimmickSequenceId < keys[j].GimmickSequenceId
|
||||
})
|
||||
if len(keys) > masterdata.MaxUserGimmickRows {
|
||||
keys = keys[:masterdata.MaxUserGimmickRows]
|
||||
}
|
||||
|
||||
records := make([]map[string]any, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
|
||||
Reference in New Issue
Block a user