Save endgame progress, team presets, technique support and camera controls
This commit is contained in:
1 parent
a681affdb3
commit
639cef7d19
52 files changed
+11940
-766
No files matched your search
@@ -3,110 +3,212 @@ package gameserver
|
||||
import (
|
||||
"gac-hkrpg-go/internal/common"
|
||||
goproto "gac-hkrpg-go/protocol/proto"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func commonToLineupAvatars(f *common.FreesrData) []*goproto.LineupAvatar {
|
||||
return common.ToLineupAvatars(f)
|
||||
}
|
||||
|
||||
func init() {
|
||||
handle("GetAllLineupData", func(s *Session, req *goproto.GetAllLineupDataCsReq, rsp *goproto.GetAllLineupDataScRsp) error {
|
||||
player := s.JSON()
|
||||
if player == nil {
|
||||
return nil
|
||||
handle("GetAllLineupData", func(s *Session, _ *goproto.GetAllLineupDataCsReq, rsp *goproto.GetAllLineupDataScRsp) error {
|
||||
var err error
|
||||
rsp.LineupList, err = allPresetLineups(s)
|
||||
if p := s.JSON(); p != nil {
|
||||
rsp.CurIndex = p.ActiveTeamPreset
|
||||
}
|
||||
rsp.LineupList = append(rsp.LineupList, &goproto.LineupInfo{
|
||||
ExtraLineupType: goproto.ExtraLineupType_ExtraLineupType_LineupNone,
|
||||
Name: "Squad 1",
|
||||
Mp: 5,
|
||||
MaxMp: 5,
|
||||
AvatarList: commonToLineupAvatars(player),
|
||||
})
|
||||
return err
|
||||
})
|
||||
handle("GetCurLineupData", func(s *Session, _ *goproto.GetCurLineupDataCsReq, rsp *goproto.GetCurLineupDataScRsp) error {
|
||||
rsp.Lineup = s.techniqueLineup()
|
||||
return nil
|
||||
})
|
||||
|
||||
handle("GetCurLineupData", func(s *Session, req *goproto.GetCurLineupDataCsReq, rsp *goproto.GetCurLineupDataScRsp) error {
|
||||
player := s.JSON()
|
||||
if player == nil {
|
||||
return nil
|
||||
}
|
||||
rsp.Lineup = &goproto.LineupInfo{
|
||||
ExtraLineupType: goproto.ExtraLineupType_ExtraLineupType_LineupNone,
|
||||
Name: "Squad 1",
|
||||
Mp: 5,
|
||||
MaxMp: 5,
|
||||
AvatarList: commonToLineupAvatars(player),
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
handle("JoinLineup", func(s *Session, req *goproto.JoinLineupCsReq, rsp *goproto.JoinLineupScRsp) error {
|
||||
player := s.JSON()
|
||||
if player == nil {
|
||||
code, err := s.presetEditCode(req.Index, req.ExtraLineupType, req.IsVirtual)
|
||||
rsp.Retcode = code
|
||||
if err != nil || code != 0 {
|
||||
return err
|
||||
}
|
||||
saved := s.JSON().TeamPreset(req.Index)
|
||||
saved.Avatars[req.Slot] = req.BaseAvatarId
|
||||
if code := validatePresetMembers(s.JSON(), saved.Avatars); code != 0 {
|
||||
rsp.Retcode = code
|
||||
return nil
|
||||
}
|
||||
player.Lineups[req.Slot] = req.BaseAvatarId
|
||||
player.SavePersistent()
|
||||
return refreshLineup(s)
|
||||
return s.savePreset(req.Index, saved)
|
||||
})
|
||||
|
||||
handle("ReplaceLineup", func(s *Session, req *goproto.ReplaceLineupCsReq, rsp *goproto.ReplaceLineupScRsp) error {
|
||||
player := s.JSON()
|
||||
if player == nil {
|
||||
code, err := s.presetEditCode(req.Index, req.ExtraLineupType, req.IsVirtual)
|
||||
rsp.Retcode = code
|
||||
if err != nil || code != 0 {
|
||||
return err
|
||||
}
|
||||
saved := s.JSON().TeamPreset(req.Index)
|
||||
saved.Avatars = map[uint32]uint32{}
|
||||
for _, a := range req.LineupSlotList {
|
||||
saved.Avatars[a.Slot] = a.Id
|
||||
}
|
||||
if code := validatePresetMembers(s.JSON(), saved.Avatars); code != 0 {
|
||||
rsp.Retcode = code
|
||||
return nil
|
||||
}
|
||||
for _, item := range req.LineupSlotList {
|
||||
player.Lineups[item.Slot] = item.Id
|
||||
}
|
||||
player.SavePersistent()
|
||||
return refreshLineup(s)
|
||||
})
|
||||
|
||||
handle("SwapLineup", func(s *Session, req *goproto.SwapLineupCsReq, rsp *goproto.SwapLineupScRsp) error {
|
||||
player := s.JSON()
|
||||
if player == nil {
|
||||
if req.Index == s.JSON().ActiveTeamPreset && len(common.ToLineupAvatars(&common.FreesrData{Lineups: saved.Avatars, Avatars: s.JSON().Avatars})) == 0 {
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_LINEUP_IS_EMPTY)
|
||||
return nil
|
||||
}
|
||||
// MPIEGFCNBEN / ENBIBCPPLDC are the obfuscated src/dst slots; the swap
|
||||
// is symmetric so the mapping direction doesn't matter.
|
||||
srcSlot, dstSlot := req.MPIEGFCNBEN, req.ENBIBCPPLDC
|
||||
srcAvatar := player.Lineups[srcSlot]
|
||||
dstAvatar := player.Lineups[dstSlot]
|
||||
player.Lineups[srcSlot] = dstAvatar
|
||||
player.Lineups[dstSlot] = srcAvatar
|
||||
player.SavePersistent()
|
||||
return refreshLineup(s)
|
||||
})
|
||||
|
||||
handle("SwitchLineupIndex", func(s *Session, req *goproto.SwitchLineupIndexCsReq, rsp *goproto.SwitchLineupIndexScRsp) error {
|
||||
return refreshLineup(s)
|
||||
})
|
||||
|
||||
handle("GetLineupAvatarData", func(s *Session, req *goproto.GetLineupAvatarDataCsReq, rsp *goproto.GetLineupAvatarDataScRsp) error {
|
||||
player := s.JSON()
|
||||
if player != nil {
|
||||
for _, slot := range player.SortedLineupKeys() {
|
||||
avatarID := player.Lineups[slot]
|
||||
if avatarID == 0 {
|
||||
continue
|
||||
saved.LeaderSlot = req.LeaderSlot
|
||||
if saved.Avatars[saved.LeaderSlot] == 0 {
|
||||
for _, slot := range sortedU32Keys2(saved.Avatars) {
|
||||
if saved.Avatars[slot] != 0 {
|
||||
saved.LeaderSlot = slot
|
||||
break
|
||||
}
|
||||
rsp.AvatarDataList = append(rsp.AvatarDataList, &goproto.LineupAvatarData{
|
||||
AvatarType: goproto.AvatarType_AVATAR_FORMAL_TYPE,
|
||||
Hp: 10000,
|
||||
Id: avatarID,
|
||||
})
|
||||
}
|
||||
}
|
||||
rsp.Retcode = 0
|
||||
return nil
|
||||
return s.savePreset(req.Index, saved)
|
||||
})
|
||||
handle("SwapLineup", func(s *Session, req *goproto.SwapLineupCsReq, rsp *goproto.SwapLineupScRsp) error {
|
||||
code, err := s.presetEditCode(req.Index, req.ExtraLineupType, req.IsVirtual)
|
||||
rsp.Retcode = code
|
||||
if err != nil || code != 0 {
|
||||
return err
|
||||
}
|
||||
saved := s.JSON().TeamPreset(req.Index)
|
||||
src, dst := req.MPIEGFCNBEN, req.ENBIBCPPLDC
|
||||
saved.Avatars[src], saved.Avatars[dst] = saved.Avatars[dst], saved.Avatars[src]
|
||||
if code := validatePresetMembers(s.JSON(), saved.Avatars); code != 0 {
|
||||
rsp.Retcode = code
|
||||
return nil
|
||||
}
|
||||
if saved.LeaderSlot == src {
|
||||
saved.LeaderSlot = dst
|
||||
} else if saved.LeaderSlot == dst {
|
||||
saved.LeaderSlot = src
|
||||
}
|
||||
return s.savePreset(req.Index, saved)
|
||||
})
|
||||
handle("SwitchLineupIndex", func(s *Session, req *goproto.SwitchLineupIndexCsReq, rsp *goproto.SwitchLineupIndexScRsp) error {
|
||||
code, err := s.presetEditCode(req.Index, goproto.ExtraLineupType_ExtraLineupType_LineupNone, false)
|
||||
rsp.Retcode = code
|
||||
if err != nil || code != 0 {
|
||||
return err
|
||||
}
|
||||
if s.ChallengeRun != nil {
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_LINEUP_NOT_ALLOW_EDIT)
|
||||
return nil
|
||||
}
|
||||
p := s.JSON()
|
||||
saved := p.TeamPreset(req.Index)
|
||||
tmp := *p
|
||||
tmp.Lineups = saved.Avatars
|
||||
if len(common.ToLineupAvatars(&tmp)) == 0 {
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_LINEUP_IS_EMPTY)
|
||||
return nil
|
||||
}
|
||||
// Retain the outgoing team, including edits made through existing APIs.
|
||||
if err := p.SaveTeamPreset(p.ActiveTeamPreset, p.TeamPreset(p.ActiveTeamPreset)); err != nil {
|
||||
return err
|
||||
}
|
||||
previous := p.ActiveTeamPreset
|
||||
p.ActiveTeamPreset = req.Index
|
||||
if err := p.SaveTeamPreset(req.Index, saved); err != nil {
|
||||
p.ActiveTeamPreset = previous
|
||||
return err
|
||||
}
|
||||
rsp.Index = req.Index
|
||||
return s.publishPreset(req.Index, saved)
|
||||
})
|
||||
handle("SetLineupName", func(s *Session, req *goproto.SetLineupNameCsReq, rsp *goproto.SetLineupNameScRsp) error {
|
||||
code, err := s.presetEditCode(req.Index, goproto.ExtraLineupType_ExtraLineupType_LineupNone, false)
|
||||
rsp.Retcode = code
|
||||
if err != nil || code != 0 {
|
||||
return err
|
||||
}
|
||||
rules, err := common.LoadTeamPresetRules()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name := strings.TrimSpace(req.Name)
|
||||
if !utf8.ValidString(name) || name == "" || len(utf16.Encode([]rune(name))) > rules.MaxNameLength {
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_LINEUP_NAME_FORMAT_ERROR)
|
||||
return nil
|
||||
}
|
||||
saved := s.JSON().TeamPreset(req.Index)
|
||||
saved.Name = name
|
||||
rsp.Index = req.Index
|
||||
rsp.Name = name
|
||||
return s.savePreset(req.Index, saved)
|
||||
})
|
||||
handle("MarkPresetLineup", func(s *Session, req *goproto.MarkPresetLineupCsReq, rsp *goproto.MarkPresetLineupScRsp) error {
|
||||
code, err := s.presetEditCode(req.Index, goproto.ExtraLineupType_ExtraLineupType_LineupNone, false)
|
||||
rsp.Retcode = code
|
||||
if err != nil || code != 0 {
|
||||
return err
|
||||
}
|
||||
saved := s.JSON().TeamPreset(req.Index)
|
||||
saved.Favourite = req.IECKKCHJMLP
|
||||
rsp.Index = req.Index
|
||||
rsp.IECKKCHJMLP = req.IECKKCHJMLP
|
||||
return s.savePreset(req.Index, saved)
|
||||
})
|
||||
|
||||
handle("QuitLineup", func(s *Session, req *goproto.QuitLineupCsReq, rsp *goproto.QuitLineupScRsp) error {
|
||||
code, err := s.presetEditCode(req.Index, req.ExtraLineupType, req.IsVirtual)
|
||||
rsp.Retcode = code
|
||||
if err != nil || code != 0 {
|
||||
return err
|
||||
}
|
||||
saved := s.JSON().TeamPreset(req.Index)
|
||||
for slot, id := range saved.Avatars {
|
||||
if id == req.BaseAvatarId {
|
||||
delete(saved.Avatars, slot)
|
||||
}
|
||||
}
|
||||
var nonempty bool
|
||||
for _, id := range saved.Avatars {
|
||||
if id != 0 {
|
||||
nonempty = true
|
||||
}
|
||||
}
|
||||
if !nonempty && req.Index == s.JSON().ActiveTeamPreset {
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_LINEUP_ONLY_ONE_MEMBER)
|
||||
return nil
|
||||
}
|
||||
if saved.Avatars[saved.LeaderSlot] == 0 {
|
||||
for _, slot := range sortedU32Keys2(saved.Avatars) {
|
||||
if saved.Avatars[slot] != 0 {
|
||||
saved.LeaderSlot = slot
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.savePreset(req.Index, saved)
|
||||
})
|
||||
handle("GetLineupAvatarData", func(s *Session, _ *goproto.GetLineupAvatarDataCsReq, rsp *goproto.GetLineupAvatarDataScRsp) error {
|
||||
if lineup := s.techniqueLineup(); lineup != nil {
|
||||
for _, a := range lineup.AvatarList {
|
||||
rsp.AvatarDataList = append(rsp.AvatarDataList, &goproto.LineupAvatarData{AvatarType: a.AvatarType, Hp: a.Hp, Id: a.Id})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
handle("ChangeLineupLeader", func(s *Session, req *goproto.ChangeLineupLeaderCsReq, rsp *goproto.ChangeLineupLeaderScRsp) error {
|
||||
rsp.Slot = req.Slot
|
||||
if lineup := s.techniqueLineup(); lineup != nil {
|
||||
for _, a := range lineup.AvatarList {
|
||||
if a.Slot == req.Slot {
|
||||
s.leaderSlot = req.Slot
|
||||
rsp.Slot = req.Slot
|
||||
if s.ChallengeRun == nil {
|
||||
p := s.JSON()
|
||||
saved := p.TeamPreset(p.ActiveTeamPreset)
|
||||
saved.LeaderSlot = req.Slot
|
||||
return p.SaveTeamPreset(p.ActiveTeamPreset, saved)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_LINEUP_NOT_VALID_LEADER)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -118,13 +220,7 @@ func refreshLineup(s *Session) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
lineup := &goproto.LineupInfo{
|
||||
ExtraLineupType: goproto.ExtraLineupType_ExtraLineupType_LineupNone,
|
||||
Name: "Squad 1",
|
||||
AvatarList: commonToLineupAvatars(player),
|
||||
MaxMp: 5,
|
||||
Mp: 5,
|
||||
}
|
||||
lineup := s.techniqueLineup()
|
||||
|
||||
notify := &goproto.SceneGroupRefreshScNotify{
|
||||
FloorId: player.Scene.FloorID,
|
||||
@@ -135,8 +231,18 @@ func refreshLineup(s *Session) error {
|
||||
State: 0,
|
||||
GroupRefreshType: goproto.SceneGroupRefreshType_SCENE_GROUP_REFRESH_TYPE_LOADED,
|
||||
}
|
||||
for _, slot := range sortedU32Keys2(s.partyActorSlots) {
|
||||
if player.Lineups[slot] == 0 {
|
||||
group.RefreshEntity = append(group.RefreshEntity, &goproto.SceneEntityRefreshInfo{RefreshType: &goproto.SceneEntityRefreshInfo_DeleteEntity{DeleteEntity: slot + 1}})
|
||||
}
|
||||
}
|
||||
s.partyActorSlots = map[uint32]bool{}
|
||||
for _, slot := range player.SortedLineupKeys() {
|
||||
avatarID := player.Lineups[slot]
|
||||
if avatarID == 0 {
|
||||
continue
|
||||
}
|
||||
s.partyActorSlots[slot] = true
|
||||
group.RefreshEntity = append(group.RefreshEntity, &goproto.SceneEntityRefreshInfo{
|
||||
RefreshType: &goproto.SceneEntityRefreshInfo_AddEntity{
|
||||
AddEntity: &goproto.SceneEntityInfo{
|
||||
|
||||
Reference in new issue
Block a user