Update GaCy-GO
This commit is contained in:
1 parent
da8a32f60d
commit
0cbe460e49
345 files changed
+98202
-77559
No files matched your search
@@ -0,0 +1,179 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type StellaJumpCase struct {
|
||||
ID uint32 `json:"GameBoyCaseID"`
|
||||
Challenges []uint32 `json:"GameBoyChallengeIDList"`
|
||||
CheatQuestID uint32
|
||||
FDGroupID, FDHardInstanceID, FDHardEntityID, FDCheatInstanceID, FDCheatEntityID uint32
|
||||
}
|
||||
|
||||
func LoadStellaJumpCases() (map[uint32]StellaJumpCase, error) {
|
||||
raw, err := ReadResourceFile("resources/StellaJumpConfig.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"`
|
||||
Cases []StellaJumpCase `json:"cases"`
|
||||
}
|
||||
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 == "" || len(resource.Cases) == 0 {
|
||||
return nil, fmt.Errorf("Stella Jump catalog provenance invalid")
|
||||
}
|
||||
cases := make(map[uint32]StellaJumpCase, len(resource.Cases))
|
||||
for _, row := range resource.Cases {
|
||||
if _, exists := cases[row.ID]; row.ID == 0 || exists || row.FDGroupID == 0 || row.FDHardInstanceID == 0 || row.FDCheatInstanceID == 0 {
|
||||
return nil, fmt.Errorf("Stella Jump case invalid")
|
||||
}
|
||||
seen := map[uint32]bool{}
|
||||
for _, id := range row.Challenges {
|
||||
if id == 0 || seen[id] {
|
||||
return nil, fmt.Errorf("Stella Jump challenge invalid")
|
||||
}
|
||||
seen[id] = true
|
||||
}
|
||||
cases[row.ID] = row
|
||||
}
|
||||
return cases, nil
|
||||
}
|
||||
|
||||
type StellaJumpRecord struct {
|
||||
BestTime uint64 `json:"best_time"`
|
||||
FinishedChallenges []uint32 `json:"finished_challenges"`
|
||||
CheatInput bool `json:"cheat_input"`
|
||||
CheatMode bool `json:"cheat_mode"`
|
||||
}
|
||||
|
||||
func SaveStellaJumpCheatSetting(id uint32, input bool, enabled bool) error {
|
||||
cases, err := LoadStellaJumpCases()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := cases[id]; !ok {
|
||||
return fmt.Errorf("unknown Stella Jump case %d", id)
|
||||
}
|
||||
persistentWriteMu.Lock()
|
||||
defer persistentWriteMu.Unlock()
|
||||
unlock, err := lockPersistentFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer unlock()
|
||||
root, err := readCurrencyWarsPersistentRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
records := map[uint32]StellaJumpRecord{}
|
||||
if raw, exists := root["stella_jump"]; exists {
|
||||
if err = json.Unmarshal(raw, &records); err != nil {
|
||||
return err
|
||||
}
|
||||
if records == nil {
|
||||
records = map[uint32]StellaJumpRecord{}
|
||||
}
|
||||
}
|
||||
record := records[id]
|
||||
if input {
|
||||
record.CheatInput = enabled
|
||||
} else {
|
||||
record.CheatMode = enabled
|
||||
}
|
||||
records[id] = record
|
||||
root["stella_jump"], err = json.Marshal(records)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeJSONAtomic("persistent", root)
|
||||
}
|
||||
|
||||
func ReadStellaJumpRecord(id uint32) (StellaJumpRecord, error) {
|
||||
root, err := readCurrencyWarsPersistentRoot()
|
||||
if err != nil {
|
||||
return StellaJumpRecord{}, err
|
||||
}
|
||||
var records map[uint32]StellaJumpRecord
|
||||
if raw, exists := root["stella_jump"]; exists {
|
||||
if err = json.Unmarshal(raw, &records); err != nil {
|
||||
return StellaJumpRecord{}, err
|
||||
}
|
||||
}
|
||||
return records[id], nil
|
||||
}
|
||||
|
||||
// Merge under the shared process/file locks. An old game session cannot replace
|
||||
// another case's score, CW snapshot, or a switch changed through the SDK.
|
||||
func SaveStellaJumpResult(id uint32, elapsed uint64, challenges []uint32) (StellaJumpRecord, error) {
|
||||
cases, err := LoadStellaJumpCases()
|
||||
if err != nil {
|
||||
return StellaJumpRecord{}, err
|
||||
}
|
||||
row, ok := cases[id]
|
||||
if !ok {
|
||||
return StellaJumpRecord{}, fmt.Errorf("unknown Stella Jump case %d", id)
|
||||
}
|
||||
allowed := map[uint32]bool{}
|
||||
for _, v := range row.Challenges {
|
||||
allowed[v] = true
|
||||
}
|
||||
for _, v := range challenges {
|
||||
if !allowed[v] {
|
||||
return StellaJumpRecord{}, fmt.Errorf("challenge %d not in case %d", v, id)
|
||||
}
|
||||
}
|
||||
persistentWriteMu.Lock()
|
||||
defer persistentWriteMu.Unlock()
|
||||
unlock, err := lockPersistentFile()
|
||||
if err != nil {
|
||||
return StellaJumpRecord{}, err
|
||||
}
|
||||
defer unlock()
|
||||
root, err := readCurrencyWarsPersistentRoot()
|
||||
if err != nil {
|
||||
return StellaJumpRecord{}, err
|
||||
}
|
||||
records := map[uint32]StellaJumpRecord{}
|
||||
if raw, exists := root["stella_jump"]; exists {
|
||||
if err = json.Unmarshal(raw, &records); err != nil {
|
||||
return StellaJumpRecord{}, err
|
||||
}
|
||||
if records == nil {
|
||||
records = map[uint32]StellaJumpRecord{}
|
||||
}
|
||||
}
|
||||
record := records[id]
|
||||
if elapsed != 0 && (record.BestTime == 0 || elapsed < record.BestTime) {
|
||||
record.BestTime = elapsed
|
||||
}
|
||||
seen := map[uint32]bool{}
|
||||
for _, v := range record.FinishedChallenges {
|
||||
seen[v] = true
|
||||
}
|
||||
for _, v := range challenges {
|
||||
if !seen[v] {
|
||||
record.FinishedChallenges = append(record.FinishedChallenges, v)
|
||||
seen[v] = true
|
||||
}
|
||||
}
|
||||
records[id] = record
|
||||
encoded, err := json.Marshal(records)
|
||||
if err != nil {
|
||||
return StellaJumpRecord{}, err
|
||||
}
|
||||
root["stella_jump"] = encoded
|
||||
if err = writeJSONAtomic("persistent", root); err != nil {
|
||||
return StellaJumpRecord{}, fmt.Errorf("save Stella Jump case %s: %w", strconv.FormatUint(uint64(id), 10), err)
|
||||
}
|
||||
return record, nil
|
||||
}
|
||||
Reference in new issue
Block a user