diff --git a/api/common.go b/api/common.go index e1666f5..a8496ed 100644 --- a/api/common.go +++ b/api/common.go @@ -52,7 +52,6 @@ func Init(mux *http.ServeMux) error { mux.HandleFunc("GET /game/classicsessioncount", handleGameClassicSessionCount) // savedata - mux.HandleFunc("GET /savedata/get", legacyHandleGetSaveData) mux.HandleFunc("POST /savedata/update", legacyHandleSaveData) mux.HandleFunc("GET /savedata/delete", legacyHandleSaveData) // TODO use deleteSystemSave mux.HandleFunc("POST /savedata/clear", legacyHandleSaveData) // TODO use clearSessionData diff --git a/api/endpoints.go b/api/endpoints.go index f43238c..4e4fa90 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -173,8 +173,7 @@ func handleGetSessionData(w http.ResponseWriter, r *http.Request) { return } - var save any - save, err = savedata.Get(uuid, 1, slot) + save, err := savedata.Session(uuid, slot) if errors.Is(err, sql.ErrNoRows) { http.Error(w, err.Error(), http.StatusNotFound) return @@ -190,54 +189,6 @@ func handleGetSessionData(w http.ResponseWriter, r *http.Request) { const legacyClientSessionId = "LEGACY_CLIENT" -func legacyHandleGetSaveData(w http.ResponseWriter, r *http.Request) { - uuid, err := uuidFromRequest(r) - if err != nil { - httpError(w, r, err, http.StatusBadRequest) - return - } - - datatype := -1 - if r.URL.Query().Has("datatype") { - datatype, err = strconv.Atoi(r.URL.Query().Get("datatype")) - if err != nil { - httpError(w, r, err, http.StatusBadRequest) - return - } - } - - var slot int - if r.URL.Query().Has("slot") { - slot, err = strconv.Atoi(r.URL.Query().Get("slot")) - if err != nil { - httpError(w, r, err, http.StatusBadRequest) - return - } - } - - var save any - if datatype == 0 { - err = db.UpdateActiveSession(uuid, legacyClientSessionId) // we dont have a client id - if err != nil { - httpError(w, r, fmt.Errorf("failed to update active session: %s", err), http.StatusBadRequest) - return - } - } - - save, err = savedata.Get(uuid, datatype, slot) - if errors.Is(err, sql.ErrNoRows) { - http.Error(w, err.Error(), http.StatusNotFound) - return - } - - if err != nil { - httpError(w, r, err, http.StatusInternalServerError) - return - } - - writeJSON(w, r, save) -} - // FIXME UNFINISHED!!! /*func clearSessionData(w http.ResponseWriter, r *http.Request) { uuid, err := uuidFromRequest(r) @@ -438,8 +389,8 @@ func legacyHandleSaveData(w http.ResponseWriter, r *http.Request) { } var save any - // /savedata/get and /savedata/delete specify datatype, but don't expect data in body - if r.URL.Path != "/savedata/get" && r.URL.Path != "/savedata/delete" { + // /savedata/delete specify datatype, but don't expect data in body + if r.URL.Path != "/savedata/delete" { if datatype == 0 { var system defs.SystemSaveData err = json.NewDecoder(r.Body).Decode(&system) @@ -463,74 +414,58 @@ func legacyHandleSaveData(w http.ResponseWriter, r *http.Request) { } var active bool - if r.URL.Path == "/savedata/get" { - if datatype == 0 { - err = db.UpdateActiveSession(uuid, clientSessionId) + active, err = db.IsActiveSession(uuid, clientSessionId) + if err != nil { + httpError(w, r, fmt.Errorf("failed to check active session: %s", err), http.StatusBadRequest) + return + } + + // TODO: make this not suck + if !active && r.URL.Path != "/savedata/clear" { + httpError(w, r, fmt.Errorf("session out of date: not active"), http.StatusBadRequest) + return + } + + var trainerId, secretId int + + if r.URL.Path != "/savedata/update" || datatype == 1 { + if r.URL.Query().Has("trainerId") && r.URL.Query().Has("secretId") { + trainerId, err = strconv.Atoi(r.URL.Query().Get("trainerId")) + if err != nil { + httpError(w, r, err, http.StatusBadRequest) + return + } + + secretId, err = strconv.Atoi(r.URL.Query().Get("secretId")) if err != nil { - httpError(w, r, fmt.Errorf("failed to update active session: %s", err), http.StatusBadRequest) + httpError(w, r, err, http.StatusBadRequest) return } } } else { - active, err = db.IsActiveSession(uuid, clientSessionId) - if err != nil { - httpError(w, r, fmt.Errorf("failed to check active session: %s", err), http.StatusBadRequest) - return - } + trainerId = save.(defs.SystemSaveData).TrainerId + secretId = save.(defs.SystemSaveData).SecretId + } - // TODO: make this not suck - if !active && r.URL.Path != "/savedata/clear" { - httpError(w, r, fmt.Errorf("session out of date: not active"), http.StatusBadRequest) - return - } + storedTrainerId, storedSecretId, err := db.FetchTrainerIds(uuid) + if err != nil { + httpError(w, r, err, http.StatusInternalServerError) + return + } - var trainerId, secretId int - - if r.URL.Path != "/savedata/update" || datatype == 1 { - if r.URL.Query().Has("trainerId") && r.URL.Query().Has("secretId") { - trainerId, err = strconv.Atoi(r.URL.Query().Get("trainerId")) - if err != nil { - httpError(w, r, err, http.StatusBadRequest) - return - } - - secretId, err = strconv.Atoi(r.URL.Query().Get("secretId")) - if err != nil { - httpError(w, r, err, http.StatusBadRequest) - return - } - } - } else { - trainerId = save.(defs.SystemSaveData).TrainerId - secretId = save.(defs.SystemSaveData).SecretId + if storedTrainerId > 0 || storedSecretId > 0 { + if trainerId != storedTrainerId || secretId != storedSecretId { + httpError(w, r, fmt.Errorf("session out of date: stored trainer or secret ID does not match"), http.StatusBadRequest) + return } - - storedTrainerId, storedSecretId, err := db.FetchTrainerIds(uuid) - if err != nil { + } else { + if err := db.UpdateTrainerIds(trainerId, secretId, uuid); err != nil { httpError(w, r, err, http.StatusInternalServerError) return } - - if storedTrainerId > 0 || storedSecretId > 0 { - if trainerId != storedTrainerId || secretId != storedSecretId { - httpError(w, r, fmt.Errorf("session out of date: stored trainer or secret ID does not match"), http.StatusBadRequest) - return - } - } else { - if err := db.UpdateTrainerIds(trainerId, secretId, uuid); err != nil { - httpError(w, r, err, http.StatusInternalServerError) - return - } - } } switch r.URL.Path { - case "/savedata/get": - save, err = savedata.Get(uuid, datatype, slot) - if errors.Is(err, sql.ErrNoRows) { - http.Error(w, err.Error(), http.StatusNotFound) - return - } case "/savedata/update": err = savedata.Update(uuid, slot, save) case "/savedata/delete": @@ -716,8 +651,7 @@ func handleGetSystemData(w http.ResponseWriter, r *http.Request) { return } - var save any //TODO this is always system save data - save, err = savedata.Get(uuid, 0, 0) + save, err := savedata.System(uuid) if err != nil { if errors.Is(err, sql.ErrNoRows) { http.Error(w, err.Error(), http.StatusNotFound) @@ -727,6 +661,7 @@ func handleGetSystemData(w http.ResponseWriter, r *http.Request) { return } + //TODO apply vouchers writeJSON(w, r, save) diff --git a/api/savedata/get.go b/api/savedata/get.go deleted file mode 100644 index d87abdf..0000000 --- a/api/savedata/get.go +++ /dev/null @@ -1,82 +0,0 @@ -/* - Copyright (C) 2024 Pagefault Games - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -package savedata - -import ( - "fmt" - "strconv" - - "github.com/pagefaultgames/rogueserver/db" - "github.com/pagefaultgames/rogueserver/defs" -) - -// /savedata/get - get save data -func Get(uuid []byte, datatype, slot int) (any, error) { - switch datatype { - case 0: // System - system, err := db.ReadSystemSaveData(uuid) - if err != nil { - return nil, err - } - - // TODO this should be a transaction - compensations, err := db.FetchAndClaimAccountCompensations(uuid) - if err != nil { - return nil, fmt.Errorf("failed to fetch compensations: %s", err) - } - - var needsUpdate bool - for compensationType, amount := range compensations { - system.VoucherCounts[strconv.Itoa(compensationType)] += amount - if amount > 0 { - needsUpdate = true - } - } - - if needsUpdate { - err = db.StoreSystemSaveData(uuid, system) - if err != nil { - return nil, fmt.Errorf("failed to update system save data: %s", err) - } - err = db.DeleteClaimedAccountCompensations(uuid) - if err != nil { - return nil, fmt.Errorf("failed to delete claimed compensations: %s", err) - } - - err = db.UpdateAccountStats(uuid, system.GameStats, system.VoucherCounts) - if err != nil { - return nil, fmt.Errorf("failed to update account stats: %s", err) - } - } - - return system, nil - case 1: // Session - if slot < 0 || slot >= defs.SessionSlotCount { - return nil, fmt.Errorf("slot id %d out of range", slot) - } - - session, err := db.ReadSessionSaveData(uuid, slot) - if err != nil { - return nil, err - } - - return session, nil - default: - return nil, fmt.Errorf("invalid data type") - } -} diff --git a/api/savedata/session.go b/api/savedata/session.go new file mode 100644 index 0000000..d6d54a8 --- /dev/null +++ b/api/savedata/session.go @@ -0,0 +1,24 @@ +package savedata + +import ( + "fmt" + + "github.com/pagefaultgames/rogueserver/db" + "github.com/pagefaultgames/rogueserver/defs" +) + +func Session(uuid []byte, slot int) (defs.SessionSaveData, error) { + var session defs.SessionSaveData + + if slot < 0 || slot >= defs.SessionSlotCount { + return session, fmt.Errorf("slot id %d out of range", slot) + } + + var err error + session, err = db.ReadSessionSaveData(uuid, slot) + if err != nil { + return session, err + } + + return session, nil +} diff --git a/api/savedata/system.go b/api/savedata/system.go new file mode 100644 index 0000000..104df7d --- /dev/null +++ b/api/savedata/system.go @@ -0,0 +1,48 @@ +package savedata + +import ( + "fmt" + "strconv" + + "github.com/pagefaultgames/rogueserver/db" + "github.com/pagefaultgames/rogueserver/defs" +) + +func System(uuid []byte) (defs.SystemSaveData, error) { + system, err := db.ReadSystemSaveData(uuid) + if err != nil { + return system, err + } + + // TODO this should be a transaction + compensations, err := db.FetchAndClaimAccountCompensations(uuid) + if err != nil { + return system, fmt.Errorf("failed to fetch compensations: %s", err) + } + + var needsUpdate bool + for compensationType, amount := range compensations { + system.VoucherCounts[strconv.Itoa(compensationType)] += amount + if amount > 0 { + needsUpdate = true + } + } + + if needsUpdate { + err = db.StoreSystemSaveData(uuid, system) + if err != nil { + return system, fmt.Errorf("failed to update system save data: %s", err) + } + err = db.DeleteClaimedAccountCompensations(uuid) + if err != nil { + return system, fmt.Errorf("failed to delete claimed compensations: %s", err) + } + + err = db.UpdateAccountStats(uuid, system.GameStats, system.VoucherCounts) + if err != nil { + return system, fmt.Errorf("failed to update account stats: %s", err) + } + } + + return system, nil +} \ No newline at end of file