mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-15 16:34:51 +01:00
character service to /internal
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/binary"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/internal/model"
|
||||
"erupe-ce/internal/service"
|
||||
"erupe-ce/internal/system"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
@@ -221,7 +222,7 @@ func logoutPlayer(s *Session) {
|
||||
removeSessionFromSemaphore(s)
|
||||
removeSessionFromStage(s)
|
||||
|
||||
saveData, err := GetCharacterSaveData(s, s.CharID)
|
||||
saveData, err := service.GetCharacterSaveData(s.CharID)
|
||||
if err != nil || saveData == nil {
|
||||
s.Logger.Error("Failed to get savedata")
|
||||
return
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/bfutil"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/server/channelserver/compression/nullcomp"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type SavePointer int
|
||||
|
||||
const (
|
||||
pGender = iota // +1
|
||||
pRP // +2
|
||||
pHouseTier // +5
|
||||
pHouseData // +195
|
||||
pBookshelfData // +lBookshelfData
|
||||
pGalleryData // +1748
|
||||
pToreData // +240
|
||||
pGardenData // +68
|
||||
pWeaponType // +1
|
||||
pWeaponID // +2
|
||||
pHR // +2
|
||||
pGRP // +4
|
||||
pKQF // +8
|
||||
lBookshelfData
|
||||
)
|
||||
|
||||
type CharacterSaveData struct {
|
||||
CharID uint32
|
||||
Name string
|
||||
IsNewCharacter bool
|
||||
Pointers map[SavePointer]int
|
||||
|
||||
Gender bool
|
||||
RP uint16
|
||||
HouseTier []byte
|
||||
HouseData []byte
|
||||
BookshelfData []byte
|
||||
GalleryData []byte
|
||||
ToreData []byte
|
||||
GardenData []byte
|
||||
WeaponType uint8
|
||||
WeaponID uint16
|
||||
HR uint16
|
||||
GR uint16
|
||||
KQF []byte
|
||||
|
||||
compSave []byte
|
||||
decompSave []byte
|
||||
}
|
||||
|
||||
func getPointers() map[SavePointer]int {
|
||||
pointers := map[SavePointer]int{pGender: 81, lBookshelfData: 5576}
|
||||
switch config.GetConfig().ClientID {
|
||||
case config.ZZ:
|
||||
pointers[pWeaponID] = 128522
|
||||
pointers[pWeaponType] = 128789
|
||||
pointers[pHouseTier] = 129900
|
||||
pointers[pToreData] = 130228
|
||||
pointers[pHR] = 130550
|
||||
pointers[pGRP] = 130556
|
||||
pointers[pHouseData] = 130561
|
||||
pointers[pBookshelfData] = 139928
|
||||
pointers[pGalleryData] = 140064
|
||||
pointers[pGardenData] = 142424
|
||||
pointers[pRP] = 142614
|
||||
pointers[pKQF] = 146720
|
||||
case config.Z2, config.Z1, config.G101, config.G10, config.G91, config.G9, config.G81, config.G8,
|
||||
config.G7, config.G61, config.G6, config.G52, config.G51, config.G5, config.GG, config.G32, config.G31,
|
||||
config.G3, config.G2, config.G1:
|
||||
pointers[pWeaponID] = 92522
|
||||
pointers[pWeaponType] = 92789
|
||||
pointers[pHouseTier] = 93900
|
||||
pointers[pToreData] = 94228
|
||||
pointers[pHR] = 94550
|
||||
pointers[pGRP] = 94556
|
||||
pointers[pHouseData] = 94561
|
||||
pointers[pBookshelfData] = 89118 // TODO: fix bookshelf data pointer
|
||||
pointers[pGalleryData] = 104064
|
||||
pointers[pGardenData] = 106424
|
||||
pointers[pRP] = 106614
|
||||
pointers[pKQF] = 110720
|
||||
case config.F5, config.F4:
|
||||
pointers[pWeaponID] = 60522
|
||||
pointers[pWeaponType] = 60789
|
||||
pointers[pHouseTier] = 61900
|
||||
pointers[pToreData] = 62228
|
||||
pointers[pHR] = 62550
|
||||
pointers[pHouseData] = 62561
|
||||
pointers[pBookshelfData] = 57118 // TODO: fix bookshelf data pointer
|
||||
pointers[pGalleryData] = 72064
|
||||
pointers[pGardenData] = 74424
|
||||
pointers[pRP] = 74614
|
||||
case config.S6:
|
||||
pointers[pWeaponID] = 12522
|
||||
pointers[pWeaponType] = 12789
|
||||
pointers[pHouseTier] = 13900
|
||||
pointers[pToreData] = 14228
|
||||
pointers[pHR] = 14550
|
||||
pointers[pHouseData] = 14561
|
||||
pointers[pBookshelfData] = 9118 // TODO: fix bookshelf data pointer
|
||||
pointers[pGalleryData] = 24064
|
||||
pointers[pGardenData] = 26424
|
||||
pointers[pRP] = 26614
|
||||
}
|
||||
if config.GetConfig().ClientID == config.G5 {
|
||||
pointers[lBookshelfData] = 5548
|
||||
} else if config.GetConfig().ClientID <= config.GG {
|
||||
pointers[lBookshelfData] = 4520
|
||||
}
|
||||
return pointers
|
||||
}
|
||||
|
||||
func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) {
|
||||
db, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
result, err := db.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to get savedata", zap.Error(err), zap.Uint32("charID", charID))
|
||||
return nil, err
|
||||
}
|
||||
defer result.Close()
|
||||
if !result.Next() {
|
||||
err = errors.New("no savedata found")
|
||||
s.Logger.Error("No savedata found", zap.Uint32("charID", charID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
saveData := &CharacterSaveData{
|
||||
Pointers: getPointers(),
|
||||
}
|
||||
err = result.Scan(&saveData.CharID, &saveData.compSave, &saveData.IsNewCharacter, &saveData.Name)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to scan savedata", zap.Error(err), zap.Uint32("charID", charID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if saveData.compSave == nil {
|
||||
return saveData, nil
|
||||
}
|
||||
|
||||
err = saveData.Decompress()
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to decompress savedata", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
saveData.updateStructWithSaveData()
|
||||
|
||||
return saveData, nil
|
||||
}
|
||||
|
||||
func (save *CharacterSaveData) Save(s *Session) {
|
||||
db, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if !s.kqfOverride {
|
||||
s.kqf = save.KQF
|
||||
} else {
|
||||
save.KQF = s.kqf
|
||||
}
|
||||
|
||||
save.updateSaveDataWithStruct()
|
||||
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
err := save.Compress()
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to compress savedata", zap.Error(err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Saves were not compressed
|
||||
save.compSave = save.decompSave
|
||||
}
|
||||
|
||||
_, err = db.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hr=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7
|
||||
`, save.compSave, save.HR, save.GR, save.Gender, save.WeaponType, save.WeaponID, save.CharID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID))
|
||||
}
|
||||
|
||||
db.Exec(`UPDATE user_binary SET house_tier=$1, house_data=$2, bookshelf=$3, gallery=$4, tore=$5, garden=$6 WHERE id=$7
|
||||
`, save.HouseTier, save.HouseData, save.BookshelfData, save.GalleryData, save.ToreData, save.GardenData, s.CharID)
|
||||
}
|
||||
|
||||
func (save *CharacterSaveData) Compress() error {
|
||||
var err error
|
||||
save.compSave, err = nullcomp.Compress(save.decompSave)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (save *CharacterSaveData) Decompress() error {
|
||||
var err error
|
||||
save.decompSave, err = nullcomp.Decompress(save.compSave)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This will update the character save with the values stored in the save struct
|
||||
func (save *CharacterSaveData) updateSaveDataWithStruct() {
|
||||
rpBytes := make([]byte, 2)
|
||||
binary.LittleEndian.PutUint16(rpBytes, save.RP)
|
||||
if config.GetConfig().ClientID >= config.F4 {
|
||||
copy(save.decompSave[save.Pointers[pRP]:save.Pointers[pRP]+2], rpBytes)
|
||||
}
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
copy(save.decompSave[save.Pointers[pKQF]:save.Pointers[pKQF]+8], save.KQF)
|
||||
}
|
||||
}
|
||||
|
||||
// This will update the save struct with the values stored in the character save
|
||||
func (save *CharacterSaveData) updateStructWithSaveData() {
|
||||
save.Name = stringsupport.SJISToUTF8(bfutil.UpToNull(save.decompSave[88:100]))
|
||||
if save.decompSave[save.Pointers[pGender]] == 1 {
|
||||
save.Gender = true
|
||||
} else {
|
||||
save.Gender = false
|
||||
}
|
||||
if !save.IsNewCharacter {
|
||||
if config.GetConfig().ClientID >= config.S6 {
|
||||
save.RP = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pRP] : save.Pointers[pRP]+2])
|
||||
save.HouseTier = save.decompSave[save.Pointers[pHouseTier] : save.Pointers[pHouseTier]+5]
|
||||
save.HouseData = save.decompSave[save.Pointers[pHouseData] : save.Pointers[pHouseData]+195]
|
||||
save.BookshelfData = save.decompSave[save.Pointers[pBookshelfData] : save.Pointers[pBookshelfData]+save.Pointers[lBookshelfData]]
|
||||
save.GalleryData = save.decompSave[save.Pointers[pGalleryData] : save.Pointers[pGalleryData]+1748]
|
||||
save.ToreData = save.decompSave[save.Pointers[pToreData] : save.Pointers[pToreData]+240]
|
||||
save.GardenData = save.decompSave[save.Pointers[pGardenData] : save.Pointers[pGardenData]+68]
|
||||
save.WeaponType = save.decompSave[save.Pointers[pWeaponType]]
|
||||
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pWeaponID] : save.Pointers[pWeaponID]+2])
|
||||
save.HR = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pHR] : save.Pointers[pHR]+2])
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
if save.HR == uint16(999) {
|
||||
save.GR = grpToGR(int(binary.LittleEndian.Uint32(save.decompSave[save.Pointers[pGRP] : save.Pointers[pGRP]+4])))
|
||||
}
|
||||
}
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
save.KQF = save.decompSave[save.Pointers[pKQF] : save.Pointers[pKQF]+8]
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func handleMsgMhfSexChanger(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSexChanger)
|
||||
s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"erupe-ce/internal/service"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/server/channelserver/compression/deltacomp"
|
||||
"erupe-ce/server/channelserver/compression/nullcomp"
|
||||
@@ -24,7 +25,7 @@ import (
|
||||
func handleMsgMhfSavedata(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSavedata)
|
||||
|
||||
characterSaveData, err := GetCharacterSaveData(s, s.CharID)
|
||||
characterSaveData, err := service.GetCharacterSaveData(s.GetCharID())
|
||||
if err != nil {
|
||||
s.Logger.Error("failed to retrieve character save data from db", zap.Error(err), zap.Uint32("charID", s.CharID))
|
||||
return
|
||||
@@ -41,7 +42,7 @@ func handleMsgMhfSavedata(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
// Perform diff.
|
||||
s.Logger.Info("Diffing...")
|
||||
characterSaveData.decompSave = deltacomp.ApplyDataDiff(diff, characterSaveData.decompSave)
|
||||
characterSaveData.SetDecompSave(deltacomp.ApplyDataDiff(diff, characterSaveData.GetDecompSave()))
|
||||
} else {
|
||||
dumpSaveData(s, pkt.RawDataPayload, "savedata")
|
||||
// Regular blob update.
|
||||
@@ -55,9 +56,9 @@ func handleMsgMhfSavedata(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
||||
dumpSaveData(s, saveData, "raw-savedata")
|
||||
}
|
||||
s.Logger.Info("Updating save with blob")
|
||||
characterSaveData.decompSave = saveData
|
||||
characterSaveData.SetDecompSave(saveData)
|
||||
}
|
||||
characterSaveData.updateStructWithSaveData()
|
||||
characterSaveData.UpdateStructWithSaveData()
|
||||
|
||||
// Bypass name-checker if new
|
||||
if characterSaveData.IsNewCharacter == true {
|
||||
@@ -81,40 +82,9 @@ func handleMsgMhfSavedata(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func grpToGR(n int) uint16 {
|
||||
var gr int
|
||||
a := []int{208750, 593400, 993400, 1400900, 2315900, 3340900, 4505900, 5850900, 7415900, 9230900, 11345900, 100000000}
|
||||
b := []int{7850, 8000, 8150, 9150, 10250, 11650, 13450, 15650, 18150, 21150, 23950}
|
||||
c := []int{51, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900}
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
if n < a[i] {
|
||||
if i == 0 {
|
||||
for {
|
||||
n -= 500
|
||||
if n <= 500 {
|
||||
if n < 0 {
|
||||
i--
|
||||
}
|
||||
break
|
||||
} else {
|
||||
i++
|
||||
for j := 0; j < i; j++ {
|
||||
n -= 150
|
||||
}
|
||||
}
|
||||
}
|
||||
gr = i + 2
|
||||
} else {
|
||||
n -= a[i-1]
|
||||
gr = c[i-1]
|
||||
gr += n / b[i-1]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return uint16(gr)
|
||||
func handleMsgMhfSexChanger(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSexChanger)
|
||||
s.DoAckSimpleSucceed(pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func dumpSaveData(s *Session, data []byte, suffix string) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package channelserver
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/internal/model"
|
||||
"erupe-ce/internal/service"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
@@ -161,7 +162,7 @@ func handleMsgMhfAcquireDistItem(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
||||
case 21:
|
||||
db.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.CharID)
|
||||
case 23:
|
||||
saveData, err := GetCharacterSaveData(s, s.CharID)
|
||||
saveData, err := service.GetCharacterSaveData(s.CharID)
|
||||
if err == nil {
|
||||
saveData.RP += uint16(item.Quantity)
|
||||
saveData.Save(s)
|
||||
|
||||
@@ -215,7 +215,7 @@ func handleDonateRP(s *Session, amount uint16, guild *service.Guild, _type int)
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(0)
|
||||
saveData, err := GetCharacterSaveData(s, s.CharID)
|
||||
saveData, err := service.GetCharacterSaveData(s.CharID)
|
||||
if err != nil {
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package channelserver
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/internal/model"
|
||||
"erupe-ce/internal/service"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -284,7 +285,7 @@ func handleMsgMhfPostTenrouirai(s *Session, db *sqlx.DB, p mhfpacket.MHFPacket)
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
sd, err := GetCharacterSaveData(s, s.CharID)
|
||||
sd, err := service.GetCharacterSaveData(s.CharID)
|
||||
if err == nil && sd != nil {
|
||||
sd.RP -= pkt.DonatedRP
|
||||
sd.Save(s)
|
||||
|
||||
@@ -373,8 +373,20 @@ func (s *Session) DoAckSimpleFail(ackHandle uint32, data []byte) {
|
||||
})
|
||||
}
|
||||
func (s *Session) GetCharID() uint32 {
|
||||
return s.CharID // Assuming `Session` has a field `CharID`
|
||||
return s.CharID
|
||||
}
|
||||
func (s *Session) GetName() string {
|
||||
return s.Name // Assuming `Session` has a field `CharID`
|
||||
return s.Name
|
||||
}
|
||||
|
||||
func (s *Session) Getkqf() []byte {
|
||||
return s.kqf
|
||||
}
|
||||
|
||||
func (s *Session) GetkqfOverride() bool {
|
||||
return s.kqfOverride
|
||||
}
|
||||
|
||||
func (s *Session) Setkqf(kqf []byte) {
|
||||
s.kqf = kqf
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user