Files
2026-10-28 18:54:43 +07:00

90 lines
2.6 KiB
Go

package common
import (
"encoding/hex"
"encoding/json"
"fmt"
)
type ComicDessertCycle struct {
ID uint32
ProgressAmount uint32
LevelIDList []uint32
}
type ComicDessertLevel struct {
ID uint32
LevelConfigPath string
RequiredCoin uint32
}
type ComicDessertCatalog struct {
Cycles []ComicDessertCycle
Levels []ComicDessertLevel
}
// Read the two captured flat tables. Never initialize gameplay by inventing a
// cycle/level ID, and never write user progress from this catalog reader.
func LoadComicDessertCatalog() (*ComicDessertCatalog, error) {
raw, err := ReadResourceFile("resources/ComicDessertCatalog.json")
if err != nil {
return nil, err
}
var resource struct {
Format uint32 `json:"format_version"`
Assembly string `json:"client_assembly_sha256"`
Evidence string `json:"evidence_id"`
ComicDessertCatalog
}
if err = json.Unmarshal(raw, &resource); err != nil {
return nil, err
}
digest, err := hex.DecodeString(resource.Assembly)
if err != nil || len(digest) != 32 || resource.Format != 1 || resource.Evidence == "" {
return nil, fmt.Errorf("ComicDessert catalog provenance invalid")
}
raw, err = ReadResourceFile("resources/PreviewGameplayCatalog.json")
if err != nil {
return nil, err
}
var client struct {
Assembly string `json:"client_assembly_sha256"`
}
if err = json.Unmarshal(raw, &client); err != nil || client.Assembly != resource.Assembly {
return nil, fmt.Errorf("ComicDessert/client catalog identity mismatch")
}
levels := make(map[uint32]bool, len(resource.Levels))
for _, level := range resource.Levels {
if level.ID == 0 || level.LevelConfigPath == "" || levels[level.ID] {
return nil, fmt.Errorf("invalid ComicDessert level catalog")
}
levels[level.ID] = true
}
cycles := make(map[uint32]bool, len(resource.Cycles))
for _, cycle := range resource.Cycles {
if cycle.ID == 0 || cycles[cycle.ID] || len(cycle.LevelIDList) == 0 {
return nil, fmt.Errorf("invalid ComicDessert cycle catalog")
}
cycles[cycle.ID] = true
for _, id := range cycle.LevelIDList {
if !levels[id] {
return nil, fmt.Errorf("ComicDessert cycle references absent level %d", id)
}
}
}
if len(cycles) == 0 || len(levels) == 0 {
return nil, fmt.Errorf("ComicDessert catalog is empty")
}
return &resource.ComicDessertCatalog, nil
}
func (c *ComicDessertCatalog) InitialCycle() ComicDessertCycle {
var first ComicDessertCycle
for _, cycle := range c.Cycles {
if first.ID == 0 || cycle.ProgressAmount < first.ProgressAmount || (cycle.ProgressAmount == first.ProgressAmount && cycle.ID < first.ID) {
first = cycle
}
}
return first
}