259 lines
7.9 KiB
Go
259 lines
7.9 KiB
Go
package gameserver
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
|
||
|
|
"gac-hkrpg-go/internal/common"
|
||
|
|
goproto "gac-hkrpg-go/protocol/proto"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Request/response layouts follow services/profile.zig and protocol.pb.zig at
|
||
|
|
// goproto.CommandSourceRevision. CSReq Go spellings below are legacy type names;
|
||
|
|
// handle resolves only the current CsReq command name, never numeric aliases.
|
||
|
|
func selectedProfileID(value *uint32, fallback uint32) uint32 {
|
||
|
|
if value != nil {
|
||
|
|
return *value
|
||
|
|
}
|
||
|
|
return fallback
|
||
|
|
}
|
||
|
|
|
||
|
|
func saveProfile(player *common.FreesrData, next common.ProfileSettings) error {
|
||
|
|
previous := player.Profile
|
||
|
|
player.Profile = next
|
||
|
|
if err := player.SavePersistentChecked(); err != nil {
|
||
|
|
player.Profile = previous
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func profilePlayer(s *Session) (*common.FreesrData, error) {
|
||
|
|
if p := s.JSON(); p != nil {
|
||
|
|
return p, nil
|
||
|
|
}
|
||
|
|
return nil, fmt.Errorf("profile command requires player data")
|
||
|
|
}
|
||
|
|
|
||
|
|
func fillPhoneData(p *common.FreesrData, resource *profileResources, rsp *goproto.GetPhoneDataScRsp) {
|
||
|
|
rsp.CurPhoneTheme = selectedProfileID(p.Profile.PhoneTheme, resource.CurrentPhoneTheme)
|
||
|
|
rsp.CurPhoneCase = selectedProfileID(p.Profile.PhoneCase, resource.CurrentPhoneCase)
|
||
|
|
rsp.CurChatBubble = selectedProfileID(p.Profile.ChatBubble, resource.CurrentChatBubble)
|
||
|
|
rsp.OwnedPhoneThemes = resource.PhoneThemes
|
||
|
|
rsp.OwnedPhoneCases = resource.PhoneCases
|
||
|
|
rsp.OwnedChatBubbles = resource.ChatBubbles
|
||
|
|
}
|
||
|
|
|
||
|
|
func fillPlayerBoard(p *common.FreesrData, resource *profileResources, rsp *goproto.GetPlayerBoardDataScRsp) {
|
||
|
|
rsp.CurrentHeadIconId = selectedProfileID(p.Profile.HeadIcon, resource.Icons[0])
|
||
|
|
rsp.CurrentPersonalCardId = selectedProfileID(p.Profile.PersonalCard, resource.CurrentPersonalCard)
|
||
|
|
rsp.HeadFrameInfo = resource.HeadFrame
|
||
|
|
if p.Profile.Signature != nil {
|
||
|
|
rsp.Signature = *p.Profile.Signature
|
||
|
|
}
|
||
|
|
rsp.JJDDEKIAOFC = resource.PersonalCards
|
||
|
|
for _, id := range resource.Icons {
|
||
|
|
rsp.KNINLDPFLMA = append(rsp.KNINLDPFLMA, &goproto.HeadIconData{Id: id})
|
||
|
|
}
|
||
|
|
rsp.NBIEJKLENOB = &goproto.DisplayAvatarVec{IsDisplay: true}
|
||
|
|
if p.Profile.IsDisplay != nil {
|
||
|
|
rsp.NBIEJKLENOB.IsDisplay = *p.Profile.IsDisplay
|
||
|
|
}
|
||
|
|
for _, slot := range p.SortedLineupKeys() {
|
||
|
|
id := p.Lineups[slot]
|
||
|
|
if p.Avatars[id] != nil {
|
||
|
|
rsp.KJAABDABLJJ = append(rsp.KJAABDABLJJ, id)
|
||
|
|
rsp.NBIEJKLENOB.DisplayAvatarList = append(rsp.NBIEJKLENOB.DisplayAvatarList, &goproto.DisplayAvatarData{AvatarId: id, Pos: slot})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if p.Profile.DisplayAvatars != nil {
|
||
|
|
rsp.NBIEJKLENOB.DisplayAvatarList = nil
|
||
|
|
for _, av := range *p.Profile.DisplayAvatars {
|
||
|
|
rsp.NBIEJKLENOB.DisplayAvatarList = append(rsp.NBIEJKLENOB.DisplayAvatarList, &goproto.DisplayAvatarData{AvatarId: av.AvatarID, Pos: av.Pos})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if p.Profile.AssistAvatars != nil {
|
||
|
|
rsp.KJAABDABLJJ = append([]uint32{}, (*p.Profile.AssistAvatars)...)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func init() {
|
||
|
|
handle("SelectPhoneTheme", func(s *Session, req *goproto.SelectPhoneThemeCsReq, rsp *goproto.SelectPhoneThemeScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
resource, err := loadProfileResources()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if req.ThemeId != resource.CurrentPhoneTheme && !containsU32(resource.PhoneThemes, req.ThemeId) {
|
||
|
|
rsp.Retcode = uint32(goproto.Retcode_RET_ITEM_NOT_EXIST)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.PhoneTheme = &req.ThemeId
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.CurPhoneTheme = req.ThemeId
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
handle("SelectPhoneCase", func(s *Session, req *goproto.SelectPhoneCaseCSReq, rsp *goproto.SelectPhoneCaseScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
resource, err := loadProfileResources()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if !containsU32(resource.PhoneCases, req.PhoneCaseId) {
|
||
|
|
rsp.Retcode = uint32(goproto.Retcode_RET_ITEM_NOT_EXIST)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.PhoneCase = &req.PhoneCaseId
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.CurPhoneCase = req.PhoneCaseId
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
handle("SelectChatBubble", func(s *Session, req *goproto.SelectChatBubbleCsReq, rsp *goproto.SelectChatBubbleScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
resource, err := loadProfileResources()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if req.BubbleId != resource.CurrentChatBubble && !containsU32(resource.ChatBubbles, req.BubbleId) {
|
||
|
|
rsp.Retcode = uint32(goproto.Retcode_RET_ITEM_NOT_EXIST)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.ChatBubble = &req.BubbleId
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.CurChatBubble = req.BubbleId
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
handle("SetHeadIcon", func(s *Session, req *goproto.SetHeadIconCsReq, rsp *goproto.SetHeadIconScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
resource, err := loadProfileResources()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if !containsU32(resource.Icons, req.Id) {
|
||
|
|
rsp.Retcode = uint32(goproto.Retcode_RET_ITEM_NOT_EXIST)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.HeadIcon = &req.Id
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.CurrentHeadIconId = req.Id
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
handle("SetPersonalCard", func(s *Session, req *goproto.SetPersonalCardCSReq, rsp *goproto.SetPersonalCardScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
resource, err := loadProfileResources()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if !containsU32(resource.PersonalCards, req.Id) {
|
||
|
|
rsp.Retcode = uint32(goproto.Retcode_RET_ITEM_NOT_EXIST)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.PersonalCard = &req.Id
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.CurrentPersonalCardId = req.Id
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
handle("SetSignature", func(s *Session, req *goproto.SetSignatureCsReq, rsp *goproto.SetSignatureScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.Signature = &req.Signature
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.Signature = req.Signature
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
handle("SetIsDisplayAvatarInfo", func(s *Session, req *goproto.SetIsDisplayAvatarInfoCsReq, rsp *goproto.SetIsDisplayAvatarInfoScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.IsDisplay = &req.IsDisplay
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.IsDisplay = req.IsDisplay
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
handle("SetDisplayAvatar", func(s *Session, req *goproto.SetDisplayAvatarCsReq, rsp *goproto.SetDisplayAvatarScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
list := make([]common.ProfileAvatar, 0, len(req.DisplayAvatarList))
|
||
|
|
positions, avatars := map[uint32]bool{}, map[uint32]bool{}
|
||
|
|
for _, av := range req.DisplayAvatarList {
|
||
|
|
if av == nil || p.Avatars[av.AvatarId] == nil || positions[av.Pos] || avatars[av.AvatarId] {
|
||
|
|
rsp.Retcode = uint32(goproto.Retcode_RET_AVATAR_NOT_EXIST)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
positions[av.Pos], avatars[av.AvatarId] = true, true
|
||
|
|
list = append(list, common.ProfileAvatar{AvatarID: av.AvatarId, Pos: av.Pos})
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.DisplayAvatars = &list
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.DisplayAvatarList = req.DisplayAvatarList
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
handle("SetAssistAvatar", func(s *Session, req *goproto.SetAssistAvatarCsReq, rsp *goproto.SetAssistAvatarScRsp) error {
|
||
|
|
p, err := profilePlayer(s)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
list := append([]uint32{}, req.AvatarIdList...)
|
||
|
|
if req.AvatarId != 0 && !containsU32(list, req.AvatarId) {
|
||
|
|
list = append(list, req.AvatarId)
|
||
|
|
}
|
||
|
|
seen := map[uint32]bool{}
|
||
|
|
for _, id := range list {
|
||
|
|
if p.Avatars[id] == nil || seen[id] {
|
||
|
|
rsp.Retcode = uint32(goproto.Retcode_RET_AVATAR_NOT_EXIST)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
seen[id] = true
|
||
|
|
}
|
||
|
|
next := p.Profile
|
||
|
|
next.AssistAvatars = &list
|
||
|
|
if err := saveProfile(p, next); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rsp.AvatarId, rsp.AvatarIdList = req.AvatarId, req.AvatarIdList
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
}
|