chore(merge): merge main into develop

Resolves CHANGELOG.md conflict: preserve develop's [Unreleased] block,
insert the [9.3.1] section from main, remove the duplicate
DisableSaveIntegrityCheck entry that had been in [Unreleased].
This commit is contained in:
Houmgaor
2026-03-23 11:15:20 +01:00
20 changed files with 279 additions and 101 deletions

View File

@@ -55,16 +55,23 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error)
// Verify integrity checksum if one was stored with this save.
// A nil hash means the character was saved before checksums were introduced,
// so we skip verification (the next save will compute and store the hash).
if storedHash != nil {
// DisableSaveIntegrityCheck bypasses this entirely for cross-server save transfers.
if storedHash != nil && !s.server.erupeConfig.DisableSaveIntegrityCheck {
computedHash := sha256.Sum256(saveData.decompSave)
if !bytes.Equal(storedHash, computedHash[:]) {
s.logger.Error("Savedata integrity check failed: hash mismatch",
s.logger.Error("Savedata integrity check failed: hash mismatch — "+
"if this character was imported from another server, set DisableSaveIntegrityCheck=true in config.json "+
"or run: UPDATE characters SET savedata_hash = NULL WHERE id = <charID>",
zap.Uint32("charID", charID),
zap.Binary("stored_hash", storedHash),
zap.Binary("computed_hash", computedHash[:]),
)
return recoverFromBackups(s, saveData, charID)
}
} else if storedHash != nil && s.server.erupeConfig.DisableSaveIntegrityCheck {
s.logger.Warn("Savedata integrity check skipped (DisableSaveIntegrityCheck=true)",
zap.Uint32("charID", charID),
)
}
saveData.updateStructWithSaveData()