mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 15:34:38 +01:00
133 lines
3.6 KiB
Go
133 lines
3.6 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/binary"
|
|
|
|
"erupe-ce/network/mhfpacket"
|
|
"erupe-ce/server/channelserver/compression/nullcomp"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
const (
|
|
CharacterSaveRPPointer = 0x22D16
|
|
)
|
|
|
|
type CharacterSaveData struct {
|
|
CharID uint32
|
|
Name string
|
|
RP uint16
|
|
IsNewCharacter bool
|
|
|
|
// Use provided setter/getter
|
|
baseSaveData []byte
|
|
}
|
|
|
|
func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) {
|
|
result, err := s.server.db.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID)
|
|
|
|
if err != nil {
|
|
s.logger.Error("failed to retrieve save data for character", zap.Error(err), zap.Uint32("charID", charID))
|
|
return nil, err
|
|
}
|
|
|
|
defer result.Close()
|
|
|
|
saveData := &CharacterSaveData{}
|
|
var compressedBaseSave []byte
|
|
|
|
if !result.Next() {
|
|
s.logger.Error("no results found for character save data", zap.Uint32("charID", charID))
|
|
return nil, err
|
|
}
|
|
|
|
err = result.Scan(&saveData.CharID, &compressedBaseSave, &saveData.IsNewCharacter, &saveData.Name)
|
|
|
|
if err != nil {
|
|
s.logger.Error(
|
|
"failed to retrieve save data for character",
|
|
zap.Error(err),
|
|
zap.Uint32("charID", charID),
|
|
)
|
|
|
|
return nil, err
|
|
}
|
|
|
|
if compressedBaseSave == nil {
|
|
return saveData, nil
|
|
}
|
|
|
|
decompressedBaseSave, err := nullcomp.Decompress(compressedBaseSave)
|
|
|
|
if err != nil {
|
|
s.logger.Error("Failed to decompress savedata from db", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
saveData.SetBaseSaveData(decompressedBaseSave)
|
|
|
|
return saveData, nil
|
|
}
|
|
|
|
func (save *CharacterSaveData) Save(s *Session, transaction *sql.Tx) error {
|
|
// We need to update the save data byte array before we save it back to the DB
|
|
save.updateSaveDataWithStruct()
|
|
|
|
compressedData, err := save.CompressedBaseData(s)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
updateSQL := "UPDATE characters SET savedata=$1, is_new_character=$3 WHERE id=$2"
|
|
|
|
if transaction != nil {
|
|
_, err = transaction.Exec(updateSQL, compressedData, save.CharID, save.IsNewCharacter)
|
|
} else {
|
|
_, err = s.server.db.Exec(updateSQL, compressedData, save.CharID, save.IsNewCharacter)
|
|
}
|
|
if err != nil {
|
|
s.logger.Error("failed to save character data", zap.Error(err), zap.Uint32("charID", save.CharID))
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (save *CharacterSaveData) CompressedBaseData(s *Session) ([]byte, error) {
|
|
compressedData, err := nullcomp.Compress(save.baseSaveData)
|
|
|
|
if err != nil {
|
|
s.logger.Error("failed to compress saveData", zap.Error(err), zap.Uint32("charID", save.CharID))
|
|
return nil, err
|
|
}
|
|
return compressedData, nil
|
|
}
|
|
|
|
func (save *CharacterSaveData) BaseSaveData() []byte {
|
|
return save.baseSaveData
|
|
}
|
|
|
|
func (save *CharacterSaveData) SetBaseSaveData(data []byte) {
|
|
save.baseSaveData = data
|
|
// After setting the new save byte array, we can extract the values to update our struct
|
|
// This will be useful when we save it back, we use the struct values to overwrite the saveData
|
|
save.updateStructWithSaveData()
|
|
}
|
|
|
|
// This will update the save struct with the values stored in the raw savedata arrays
|
|
func (save *CharacterSaveData) updateSaveDataWithStruct() {
|
|
rpBytes := make([]byte, 2)
|
|
binary.LittleEndian.PutUint16(rpBytes, save.RP)
|
|
copy(save.baseSaveData[CharacterSaveRPPointer:CharacterSaveRPPointer+2], rpBytes)
|
|
}
|
|
|
|
// This will update the character save struct with the values stored in the raw savedata arrays
|
|
func (save *CharacterSaveData) updateStructWithSaveData() {
|
|
save.RP = binary.LittleEndian.Uint16(save.baseSaveData[CharacterSaveRPPointer : CharacterSaveRPPointer+2])
|
|
}
|
|
|
|
func handleMsgMhfSexChanger(s *Session, p mhfpacket.MHFPacket) {
|
|
pkt := p.(*mhfpacket.MsgMhfSexChanger)
|
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
|
}
|