diff --git a/api/savedata/common.go b/api/savedata/common.go index 657d916..7c03c54 100644 --- a/api/savedata/common.go +++ b/api/savedata/common.go @@ -28,7 +28,7 @@ import ( "github.com/pagefaultgames/rogueserver/defs" ) -func readSystemSaveData(uuid []byte) (defs.SystemSaveData, error) { +func legacyReadSystemSaveData(uuid []byte) (defs.SystemSaveData, error) { var system defs.SystemSaveData file, err := os.Open("userdata/" + hex.EncodeToString(uuid) + "/system.pzs") @@ -53,7 +53,7 @@ func readSystemSaveData(uuid []byte) (defs.SystemSaveData, error) { return system, nil } -func readSessionSaveData(uuid []byte, slotID int) (defs.SessionSaveData, error) { +func legacyReadSessionSaveData(uuid []byte, slotID int) (defs.SessionSaveData, error) { var session defs.SessionSaveData fileName := "session" diff --git a/api/savedata/get.go b/api/savedata/get.go index 44e8c1b..7c844a9 100644 --- a/api/savedata/get.go +++ b/api/savedata/get.go @@ -29,7 +29,11 @@ import ( func Get(uuid []byte, datatype, slot int) (any, error) { switch datatype { case 0: // System - system, err := readSystemSaveData(uuid) + if slot != 0 { + return nil, fmt.Errorf("invalid slot id for system data") + } + + system, err := db.ReadSystemSaveData(uuid) if err != nil { return nil, err } @@ -49,7 +53,7 @@ func Get(uuid []byte, datatype, slot int) (any, error) { return nil, fmt.Errorf("slot id %d out of range", slot) } - session, err := readSessionSaveData(uuid, slot) + session, err := db.ReadSessionSaveData(uuid, slot) if err != nil { return nil, err } diff --git a/api/savedata/update.go b/api/savedata/update.go index c4ee109..1048ca5 100644 --- a/api/savedata/update.go +++ b/api/savedata/update.go @@ -18,8 +18,6 @@ package savedata import ( - "bytes" - "encoding/gob" "fmt" "log" "os" @@ -45,7 +43,6 @@ func Update(uuid []byte, slot int, save any) error { return fmt.Errorf(fmt.Sprintf("failed to create userdata folder: %s", err)) } - var filename string switch save := save.(type) { case defs.SystemSaveData: // System if save.TrainerId == 0 && save.SecretId == 0 { @@ -61,36 +58,26 @@ func Update(uuid []byte, slot int, save any) error { return fmt.Errorf("failed to update account stats: %s", err) } - filename = "system" + err = db.DeleteClaimedAccountCompensations(uuid) + if err != nil { + return fmt.Errorf("failed to delete claimed compensations: %s", err) + } + + return db.StoreSystemSaveData(uuid, save) - db.DeleteClaimedAccountCompensations(uuid) case defs.SessionSaveData: // Session if slot < 0 || slot >= defs.SessionSlotCount { return fmt.Errorf("slot id %d out of range", slot) } - filename = "session" + filename := "session" if slot != 0 { filename += strconv.Itoa(slot) } + + return db.StoreSessionSaveData(uuid, save, slot) + default: return fmt.Errorf("invalid data type") } - - var buf bytes.Buffer - err = gob.NewEncoder(&buf).Encode(save) - if err != nil { - return fmt.Errorf("failed to serialize save: %s", err) - } - - if buf.Len() == 0 { - return fmt.Errorf("tried to write empty save file") - } - - err = os.WriteFile(fmt.Sprintf("userdata/%x/%s.pzs", uuid, filename), zstdEncoder.EncodeAll(buf.Bytes(), nil), 0644) - if err != nil { - return fmt.Errorf("failed to write save to disk: %s", err) - } - - return nil } diff --git a/db/db.go b/db/db.go index 1daa8bf..070a81c 100644 --- a/db/db.go +++ b/db/db.go @@ -36,5 +36,10 @@ func Init(username, password, protocol, address, database string) error { handle.SetMaxOpenConns(1000) + handle.Exec("CREATE TABLE IF NOT EXISTS systemSaveData (uuid BINARY(16) PRIMARY KEY, data BLOB, timestamp TIMESTAMP)") + handle.Exec("CREATE TABLE IF NOT EXISTS sessionSaveData (uuid BINARY(16) PRIMARY KEY, data BLOB, timestamp TIMESTAMP)") + + //TODO iterate "userdata/accountid" and create rows for each account + return nil } diff --git a/db/savedata.go b/db/savedata.go index 3390da5..13ba6d4 100644 --- a/db/savedata.go +++ b/db/savedata.go @@ -17,6 +17,12 @@ package db +import ( + "bytes" + "encoding/gob" + "github.com/pagefaultgames/rogueserver/defs" +) + func TryAddDailyRunCompletion(uuid []byte, seed string, mode int) (bool, error) { var count int err := handle.QueryRow("SELECT COUNT(*) FROM dailyRunCompletions WHERE uuid = ? AND seed = ?", uuid, seed).Scan(&count) @@ -33,3 +39,61 @@ func TryAddDailyRunCompletion(uuid []byte, seed string, mode int) (bool, error) return true, nil } + +type DbSystemSaveData struct { + uuid []byte + data []byte +} + +type DbSessionSaveData struct { + uuid []byte + data []byte +} + +func ReadSystemSaveData(uuid []byte) (defs.SystemSaveData, error) { + var data DbSystemSaveData + err := handle.QueryRow("SELECT uuid, data FROM systemSaveData WHERE uuid = ?", uuid).Scan(&data) + + reader := bytes.NewReader(data.data) + system := defs.SystemSaveData{} + err = gob.NewDecoder(reader).Decode(&system) + return system, err +} + +func StoreSystemSaveData(uuid []byte, data defs.SystemSaveData) error { + + var buf bytes.Buffer + err := gob.NewEncoder(&buf).Encode(data) + if err != nil { + return err + } + + _, err = handle.Exec("INSERT INTO systemSaveData (uuid, data, timestamp) VALUES (?, ?, UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE data = VALUES(data), timestamp = VALUES(timestamp)", uuid, buf.Bytes()) + + return err +} + +func ReadSessionSaveData(uuid []byte, slot int) (defs.SessionSaveData, error) { + + var data DbSystemSaveData + err := handle.QueryRow("SELECT uuid, data FROM sessionSaveData WHERE uuid = ?", uuid).Scan(&data) + + reader := bytes.NewReader(data.data) + save := defs.SessionSaveData{} + err = gob.NewDecoder(reader).Decode(&save) + + return save, err +} + +func StoreSessionSaveData(uuid []byte, data defs.SessionSaveData, slot int) error { + + var buf bytes.Buffer + err := gob.NewEncoder(&buf).Encode(data) + if err != nil { + return err + } + + _, err = handle.Exec("INSERT INTO sessionSaveData (uuid, data, slot, timestamp) VALUES (?, ?, ?, UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE data = VALUES(data), timestamp = VALUES(timestamp)", uuid, buf.Bytes(), slot) + + return err +}