Files
GaCy-GO/internal/gameserver/handlers_tutorial_ids.go
2026-10-28 18:54:43 +07:00

76 lines
2.2 KiB
Go

package gameserver
import (
"encoding/json"
"fmt"
"sort"
"sync"
"gac-hkrpg-go/internal/common"
)
// Tutorial IDs come from the installed Client resource tables, not a list
// copied from an older server build. Restart after replacing these resources.
var tutorialResourceCache struct {
sync.Once
tutorials []uint32
guides []uint32
err error
}
func getTutorialResourceIDs() ([]uint32, []uint32, error) {
tutorialResourceCache.Do(func() {
var tutorialFile struct {
Entries []struct {
ID uint32 `json:"TutorialID"`
} `json:"tutorial_config"`
}
var guideFile struct {
Entries []struct {
ID uint32 `json:"GroupID"`
} `json:"tutorial_guide_config"`
}
load := func(name string, dst any) error {
path := "resources/" + name
data, err := common.ReadResourceFile(path)
if err != nil {
return fmt.Errorf("tutorial resource %s: %w", path, err)
}
if err := json.Unmarshal(data, dst); err != nil {
return fmt.Errorf("tutorial resource %s: %w", path, err)
}
return nil
}
if err := load("TutorialData.json", &tutorialFile); err != nil {
tutorialResourceCache.err = err
return
}
if err := load("TutorialGuideGroup.json", &guideFile); err != nil {
tutorialResourceCache.err = err
return
}
collect := func(ids []uint32) []uint32 {
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
out := ids[:0]
for _, id := range ids {
if id != 0 && (len(out) == 0 || id != out[len(out)-1]) {
out = append(out, id)
}
}
return out
}
for _, entry := range tutorialFile.Entries {
tutorialResourceCache.tutorials = append(tutorialResourceCache.tutorials, entry.ID)
}
for _, entry := range guideFile.Entries {
tutorialResourceCache.guides = append(tutorialResourceCache.guides, entry.ID)
}
tutorialResourceCache.tutorials = collect(tutorialResourceCache.tutorials)
tutorialResourceCache.guides = collect(tutorialResourceCache.guides)
if len(tutorialResourceCache.tutorials) == 0 || len(tutorialResourceCache.guides) == 0 {
tutorialResourceCache.err = fmt.Errorf("tutorial resource tables contain no IDs")
}
})
return tutorialResourceCache.tutorials, tutorialResourceCache.guides, tutorialResourceCache.err
}