Update GaCy-GO
This commit is contained in:
1 parent
da8a32f60d
commit
0cbe460e49
345 files changed
+98202
-77559
No files matched your search
@@ -0,0 +1,172 @@
|
||||
package gameserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"gac-hkrpg-go/internal/common"
|
||||
pb "gac-hkrpg-go/protocol/proto"
|
||||
)
|
||||
|
||||
// currencyWarsAbandonRun removes only the active run from the saved CW
|
||||
// response. Season progress and all unrelated player data remain intact.
|
||||
func currencyWarsAbandonRun(data *pb.GridFightGetDataScRsp) (uint32, bool) {
|
||||
if data == nil || data.DHFOFLFCLAH == nil {
|
||||
return 0, false
|
||||
}
|
||||
runID := data.DHFOFLFCLAH.UniqueId
|
||||
data.DHFOFLFCLAH = nil
|
||||
return runID, true
|
||||
}
|
||||
|
||||
// currencyWarsQuitSettlement builds the ordered server notifications expected
|
||||
// before GridFightQuitSettleScRsp. All packet IDs and wire tags come from the
|
||||
// current generated protocol; values are copied from the saved run/catalog.
|
||||
func currencyWarsQuitSettlement(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH) (*pb.GridFightSyncKeepWinCntNotify, *pb.GridFightSettleNotify, error) {
|
||||
if catalog == nil || run == nil || run.UniqueId == 0 {
|
||||
return nil, nil, fmt.Errorf("CW quit settlement is missing catalog or active run")
|
||||
}
|
||||
player, team, _ := cwComponents(run)
|
||||
if player == nil || team == nil {
|
||||
return nil, nil, fmt.Errorf("CW quit settlement is missing player/team components")
|
||||
}
|
||||
var stage *pb.BEEFLEJAOCN
|
||||
for _, component := range run.NAGDJGMMCBE {
|
||||
if component == nil {
|
||||
continue
|
||||
}
|
||||
if current := component.GetKLCPAAHDPJF(); current != nil {
|
||||
if stage != nil {
|
||||
return nil, nil, fmt.Errorf("CW quit settlement has duplicate stage components")
|
||||
}
|
||||
stage = current
|
||||
}
|
||||
}
|
||||
if stage == nil {
|
||||
return nil, nil, fmt.Errorf("CW quit settlement is missing the current stage component")
|
||||
}
|
||||
|
||||
avatarIDs := make([]uint32, 0, len(team.GridGameRoleList))
|
||||
seenAvatars := make(map[uint32]struct{}, len(team.GridGameRoleList))
|
||||
for _, role := range team.GridGameRoleList {
|
||||
if role == nil || role.Id == 0 {
|
||||
continue
|
||||
}
|
||||
if _, exists := seenAvatars[role.Id]; exists {
|
||||
continue
|
||||
}
|
||||
seenAvatars[role.Id] = struct{}{}
|
||||
avatarIDs = append(avatarIDs, role.Id)
|
||||
}
|
||||
sort.Slice(avatarIDs, func(i, j int) bool { return avatarIDs[i] < avatarIDs[j] })
|
||||
roles := make([]*pb.CDEAABODKCP, 0, len(team.GridGameRoleList))
|
||||
for _, role := range team.GridGameRoleList {
|
||||
if role != nil {
|
||||
roles = append(roles, role)
|
||||
}
|
||||
}
|
||||
sort.SliceStable(roles, func(i, j int) bool {
|
||||
if roles[i].Pos != roles[j].Pos {
|
||||
return roles[i].Pos < roles[j].Pos
|
||||
}
|
||||
return roles[i].UniqueId < roles[j].UniqueId
|
||||
})
|
||||
|
||||
var highestDivision common.CurrencyWarsDivision
|
||||
for _, division := range catalog.SeasonDivisions(catalog.ActiveSeasonID) {
|
||||
if division.DivisionLevel > highestDivision.DivisionLevel ||
|
||||
(division.DivisionLevel == highestDivision.DivisionLevel && division.Progress > highestDivision.Progress) {
|
||||
highestDivision = division
|
||||
}
|
||||
}
|
||||
if highestDivision.ID == 0 {
|
||||
return nil, nil, fmt.Errorf("CW quit settlement has no active-season division data")
|
||||
}
|
||||
|
||||
finish := &pb.OEDHMAHDECC{
|
||||
// GridFightSettleReason value 1 is Quit in the Client enum.
|
||||
Reason: pb.PEIJNEFOCHI_PEIJNEFOCHI_NOCIJDINKPJ,
|
||||
IsOverlock: run.IsOverlock,
|
||||
JLDDDLDNFEF: run.JLDDDLDNFEF,
|
||||
NDLIKNEKDLL: &pb.GOCIGPCDKDJ{
|
||||
LKCJAPIGEND: player.PPKKHHNEOHB,
|
||||
PAGPKOKMDBK: player.GridFightLineupHp,
|
||||
DCAHJELNJNP: stage.DCAHJELNJNP,
|
||||
EMOHLJHPOPC: stage.EMOHLJHPOPC,
|
||||
AACGBEBGDPE: run.DivisionId,
|
||||
SectionId: stage.SectionId,
|
||||
},
|
||||
PPJFPNMIFHL: &pb.GLPCEKMKLGG{GridFightAvatarList: avatarIDs},
|
||||
GridGameRoleList: roles,
|
||||
GridGameNpcList: team.GridGameNpcList,
|
||||
BossInfo: stage.BossInfo,
|
||||
CFFCNEDGCJJ: stage.CFFCNEDGCJJ,
|
||||
OAIGAGABCMK: stage.GridFightPortalBuffList,
|
||||
}
|
||||
|
||||
return &pb.GridFightSyncKeepWinCntNotify{EHBLJGIENPI: player.GDAKCOICIDA}, &pb.GridFightSettleNotify{
|
||||
FLHOPMMEGAI: run.DivisionId,
|
||||
CDANKDNACJP: highestDivision.ID,
|
||||
NMCKJPEMACM: catalog.ActiveSeasonModule().MaxRewardExp,
|
||||
BFLLJJBHLDF: finish,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// The current protocol's QuitSettle request has an empty body and a typed
|
||||
// Retcode response. A successful request abandons the active CW run; it
|
||||
// does not award a victory or mutate Adventure inventory.
|
||||
cwHandle("GridFightQuitSettle", func(s *Session, _ *pb.GridFightQuitSettleCsReq, rsp *pb.GridFightQuitSettleScRsp) error {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_NOT_IN_GAMEPLAY)
|
||||
catalog, err := common.LoadCurrencyWarsCatalog()
|
||||
if err != nil {
|
||||
PacketLog(fmt.Sprintf("CW_QUIT_SETTLE rejected reason=catalog_error error=%v", err))
|
||||
return nil
|
||||
}
|
||||
data, revision, err := readCurrencyWarsData(catalog)
|
||||
if err != nil {
|
||||
PacketLog(fmt.Sprintf("CW_QUIT_SETTLE rejected reason=snapshot_error error=%v", err))
|
||||
return nil
|
||||
}
|
||||
if revision != s.currencyWarsRevision {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_PARAM_NOT_MATCH)
|
||||
PacketLog(fmt.Sprintf("CW_QUIT_SETTLE rejected reason=session_revision_mismatch saved=%d session=%d", revision, s.currencyWarsRevision))
|
||||
return nil
|
||||
}
|
||||
if data == nil {
|
||||
PacketLog(fmt.Sprintf("CW_QUIT_SETTLE rejected reason=no_saved_data revision=%d", revision))
|
||||
return nil
|
||||
}
|
||||
run := data.DHFOFLFCLAH
|
||||
if run == nil {
|
||||
PacketLog(fmt.Sprintf("CW_QUIT_SETTLE rejected reason=no_active_run revision=%d", revision))
|
||||
return nil
|
||||
}
|
||||
runID := run.UniqueId
|
||||
keepWinCount, settlement, err := currencyWarsQuitSettlement(catalog, run)
|
||||
if err != nil {
|
||||
PacketLog(fmt.Sprintf("CW_QUIT_SETTLE rejected run=%d reason=settlement_build_error error=%v", runID, err))
|
||||
return nil
|
||||
}
|
||||
_, active := currencyWarsAbandonRun(data)
|
||||
if !active {
|
||||
return nil
|
||||
}
|
||||
if err = s.saveCurrencyWarsData(data, catalog); err != nil {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_CONF_MISS)
|
||||
PacketLog(fmt.Sprintf("CW_QUIT_SETTLE rejected run=%d reason=save_error error=%v", runID, err))
|
||||
return nil
|
||||
}
|
||||
if err = cwSend(s, keepWinCount); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = cwSend(s, settlement); err != nil {
|
||||
return err
|
||||
}
|
||||
CURRENT_BATTLE.Delete(s.Token)
|
||||
s.currencyWarsOpen = false
|
||||
rsp.Retcode = 0
|
||||
PacketLog(fmt.Sprintf("CW_QUIT_SETTLE completed run=%d revision=%d result=abandoned", runID, s.currencyWarsRevision))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user