mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-05-06 14:24:15 +02:00
feat(savedata): write back zenny/gzenny/CP to ZZ save blob
Mirrors the read path added in 47277c7: updateSaveDataWithStruct now
flushes Zenny/GZenny/CP back to the blob for ZZ, using the same
`ok && off > 0 && off+size <= len(blob)` guard so unmapped modes remain
inert.
Tests lock down byte-level idempotence — the most important invariant
for save data. Parsing a live kirito ZZ blob and immediately writing
the struct back produces a byte-identical blob, so enabling these
fields cannot silently corrupt existing player saves on the next save
cycle. Additional coverage: round-trip through both paths, non-ZZ
modes never touch the blob bytes, and truncated blobs don't panic on
write.
This commit is contained in:
@@ -171,6 +171,18 @@ func (save *CharacterSaveData) updateSaveDataWithStruct() {
|
||||
if save.Mode >= cfg.G10 {
|
||||
copy(save.decompSave[save.Pointers[pKQF]:save.Pointers[pKQF]+saveFieldKQF], save.KQF)
|
||||
}
|
||||
// Write zenny / gzenny / CP only when a validated pointer exists for the
|
||||
// current mode. Same guards as the read path: absent or zero offsets are
|
||||
// never written, so unmapped versions cannot corrupt unrelated bytes.
|
||||
if off, ok := save.Pointers[pZenny]; ok && off > 0 && off+saveFieldZenny <= len(save.decompSave) {
|
||||
binary.LittleEndian.PutUint32(save.decompSave[off:off+saveFieldZenny], save.Zenny)
|
||||
}
|
||||
if off, ok := save.Pointers[pGZenny]; ok && off > 0 && off+saveFieldGZenny <= len(save.decompSave) {
|
||||
binary.LittleEndian.PutUint32(save.decompSave[off:off+saveFieldGZenny], save.GZenny)
|
||||
}
|
||||
if off, ok := save.Pointers[pCP]; ok && off > 0 && off+saveFieldCP <= len(save.decompSave) {
|
||||
binary.LittleEndian.PutUint32(save.decompSave[off:off+saveFieldCP], save.CP)
|
||||
}
|
||||
}
|
||||
|
||||
// This will update the save struct with the values stored in the character save
|
||||
|
||||
Reference in New Issue
Block a user