Add campaign bonuses; fix parts variant/sub-stat grants and menu-pick quest resume state
Build and Push Docker images to Docker Hub / build-and-push (push) Has been cancelled

This commit is contained in:
Ilya Groshev
2026-05-25 09:31:53 +03:00
parent 2d0c0d8ef0
commit dc7c1df4fd
21 changed files with 825 additions and 69 deletions
+2 -15
View File
@@ -14,6 +14,7 @@ import (
"sync/atomic"
"time"
"lunar-tear/server/internal/campaign"
"lunar-tear/server/internal/gacha"
"lunar-tear/server/internal/masterdata"
"lunar-tear/server/internal/masterdata/memorydb"
@@ -52,23 +53,17 @@ type Catalogs struct {
BigHunt *masterdata.BigHuntCatalog
Tower *masterdata.TowerCatalog
Labyrinth *masterdata.LabyrinthCatalog
Campaign *campaign.Catalog
// Catalog-derived handlers must rebuild on every reload because they
// embed/cache pointers to specific catalog instances.
QuestHandler *questflow.QuestHandler
GachaHandler *gacha.GachaHandler
}
// Holder owns the current *Catalogs and the bin.e path. Concurrent readers
// call Get(); the single-writer Reload() rebuilds and atomically publishes.
type Holder struct {
binPath string
cur atomic.Pointer[Catalogs]
}
// NewHolder reads the binary at binPath, builds the initial catalogs, and
// returns a ready-to-use Holder. Subsequent calls to Reload() re-read the
// same path.
func NewHolder(binPath string) (*Holder, error) {
h := &Holder{binPath: binPath}
if err := h.Reload(); err != nil {
@@ -77,9 +72,6 @@ func NewHolder(binPath string) (*Holder, error) {
return h, nil
}
// Reload re-reads the bin.e from disk, rebuilds every catalog and handler,
// atomically publishes the new snapshot, and bumps the bin.e mtime so client
// caches invalidate (see service/data.go GetLatestMasterDataVersion).
func (h *Holder) Reload() error {
if err := memorydb.Init(h.binPath); err != nil {
return fmt.Errorf("memorydb.Init: %w", err)
@@ -91,16 +83,11 @@ func (h *Holder) Reload() error {
h.cur.Store(c)
now := time.Now()
if err := os.Chtimes(h.binPath, now, now); err != nil {
// Non-fatal: the catalogs swapped fine in-memory; clients may take
// longer to invalidate their cached download but server-side state is
// already coherent.
log.Printf("[runtime] os.Chtimes(%s) failed (clients may not invalidate cache): %v", h.binPath, err)
}
return nil
}
// Get returns the current snapshot. Safe for concurrent callers; the returned
// pointer is stable for the duration of the caller's use.
func (h *Holder) Get() *Catalogs {
return h.cur.Load()
}