From 57a00512e6f6841c2ac56b40ef765bea74abad33 Mon Sep 17 00:00:00 2001 From: Lawliet <84912726+L4w1i3t@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:32:57 -0400 Subject: [PATCH] Added --latest-scene flag Author: https://github.com/L4w1i3t --- server/cmd/lunar-tear/main.go | 9 +++++ server/internal/service/listbin.go | 2 +- server/internal/store/memory/snapshot.go | 48 ++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/server/cmd/lunar-tear/main.go b/server/cmd/lunar-tear/main.go index cb65e1d..f0f2d16 100644 --- a/server/cmd/lunar-tear/main.go +++ b/server/cmd/lunar-tear/main.go @@ -18,6 +18,7 @@ func main() { httpPort := flag.Int("http-port", 8080, "HTTP server port (Octo API)") host := flag.String("host", "127.0.0.1", "hostname the client will connect to") scene := flag.Int("scene", 0, "Bootstrap to scene N (0 = fresh start)") + latestScene := flag.Bool("latest-scene", false, "Bootstrap from the most recently saved snapshot (overrides -scene)") starterItems := flag.Bool("starter-items", false, "Grant starter items to new users") flag.Parse() @@ -37,6 +38,14 @@ func main() { if err := os.MkdirAll(snapshotDir, 0755); err != nil { log.Fatalf("create snapshot dir: %v", err) } + if *latestScene { + if id, ok := memory.LatestSnapshotSceneId(snapshotDir); ok { + *scene = int(id) + log.Printf("[latest-scene] auto-selected most recent snapshot: scene=%d", id) + } else { + log.Printf("[latest-scene] no snapshots found in %q; starting fresh", snapshotDir) + } + } gameConfig, err := masterdata.LoadGameConfig() if err != nil { diff --git a/server/internal/service/listbin.go b/server/internal/service/listbin.go index ff6c13a..63333b1 100644 --- a/server/internal/service/listbin.go +++ b/server/internal/service/listbin.go @@ -495,4 +495,4 @@ func objectIdToFilePathCandidates(revision, assetType, objectId string) (candida } } return candidates, entry.Size, true -} +} \ No newline at end of file diff --git a/server/internal/store/memory/snapshot.go b/server/internal/store/memory/snapshot.go index b31eac5..ce15a79 100644 --- a/server/internal/store/memory/snapshot.go +++ b/server/internal/store/memory/snapshot.go @@ -6,6 +6,8 @@ import ( "log" "os" "path/filepath" + "strconv" + "strings" "lunar-tear/server/internal/store" ) @@ -32,6 +34,52 @@ func saveSnapshot(user *store.UserState, dir string) { log.Printf("[snapshot] saved scene=%d (%d bytes)", sceneId, len(data)) } +// parseSceneId extracts the numeric scene ID from a filename of the form "scene_.json". +// Returns (0, false) if the name does not match the expected format. +func parseSceneId(name string) (int32, bool) { + if !strings.HasPrefix(name, "scene_") || !strings.HasSuffix(name, ".json") { + return 0, false + } + raw := strings.TrimSuffix(strings.TrimPrefix(name, "scene_"), ".json") + id, err := strconv.ParseInt(raw, 10, 32) + if err != nil { + return 0, false + } + return int32(id), true +} + +// LatestSnapshotSceneId scans dir for scene_*.json files and returns the scene ID +// of the most recently modified snapshot. Returns (0, false) if none are found. +func LatestSnapshotSceneId(dir string) (int32, bool) { + entries, err := os.ReadDir(dir) + if err != nil { + return 0, false + } + var latestId int32 + var latestMod int64 + for _, e := range entries { + if e.IsDir() { + continue + } + id, ok := parseSceneId(e.Name()) + if !ok { + continue + } + info, err := e.Info() + if err != nil { + continue + } + if mt := info.ModTime().UnixNano(); mt > latestMod { + latestMod = mt + latestId = id + } + } + if latestId == 0 { + return 0, false + } + return latestId, true +} + func loadSnapshot(dir string, sceneId int32) (*store.UserState, error) { path := snapshotPath(dir, sceneId) data, err := os.ReadFile(path)