docs & feat: add license & attribution notice (Apache-2.0 / GPL-3.0) and core system enhancements
This commit is contained in:
1 parent
507836d367
commit
ce6aabfc55
47 files changed
+5674
-724
No files matched your search
@@ -275,217 +275,199 @@ func cwNextRound(catalog *common.CurrencyWarsCatalog, run *pb.MPIMAEMCEFH) (*pb.
|
||||
}
|
||||
|
||||
func init() {
|
||||
cwHandle("GridFightUpdatePos", func(s *Session, req *pb.GridFightUpdatePosCsReq, rsp *pb.GridFightUpdatePosScRsp) error {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_PARAM_NOT_MATCH)
|
||||
if _, active := CURRENT_BATTLE.Load(s.Token); active {
|
||||
PacketLog("CW_UPDATE_POS rejected reason=battle_active")
|
||||
return nil
|
||||
}
|
||||
catalog, err := common.LoadCurrencyWarsCatalog()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, revision, err := readCurrencyWarsData(catalog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if data == nil || data.DHFOFLFCLAH == nil {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_NOT_IN_GAMEPLAY)
|
||||
return nil
|
||||
}
|
||||
if revision != s.currencyWarsRevision {
|
||||
return nil
|
||||
}
|
||||
run := data.DHFOFLFCLAH
|
||||
if run.FMIGOKIDKJL != nil || len(req.AAKDHMHCMLP) == 0 {
|
||||
PacketLog("CW_UPDATE_POS rejected reason=not_preparing_or_empty")
|
||||
return nil
|
||||
}
|
||||
player, team, _ := cwComponents(run)
|
||||
if player == nil || team == nil {
|
||||
return nil
|
||||
}
|
||||
front, err := catalog.IntegerRule("GridFight_Front_AvatarMaxNum")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
back, err := catalog.IntegerRule("GridFight_Back_AvatarMaxNum")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
activeEnd := uint64(front + back)
|
||||
overflow, err := catalog.IntegerRule("GridFight_Bench_OverFlow_AvatarNum")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
benchEnd := activeEnd + uint64(player.MICEOJBAKGN) + uint64(overflow)
|
||||
changes := map[uint32]uint32{}
|
||||
for _, v := range req.AAKDHMHCMLP {
|
||||
if v == nil || v.UniqueId == 0 {
|
||||
cwHandle("GridFightUpdatePos", cwUpdatePositions)
|
||||
|
||||
// CmdID 8543 (GEBBMDCOLCH) -> ScRsp 8630 (ALNFEBKHCFC)
|
||||
// Protocol revision: 4.6.53 (upstream_cmdids.go).
|
||||
// Assumption: Native Client sends GEBBMDCOLCH during preparation / round transition to sync
|
||||
// the batch formation role positions (CONJCEMAHGN: MDNAGANGNKK = role UID, JFCJNHNBMCB = pos).
|
||||
// Reuse the validated formation transaction; acknowledge only after commit.
|
||||
cwHandleNamed("GEBBMDCOLCH", "ALNFEBKHCFC", func(s *Session, req *pb.GEBBMDCOLCH, rsp *pb.ALNFEBKHCFC) error {
|
||||
mapped := &pb.GridFightUpdatePosCsReq{}
|
||||
for _, entry := range req.CONJCEMAHGN {
|
||||
if entry == nil {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_PARAM_NOT_MATCH)
|
||||
return nil
|
||||
}
|
||||
if _, ok := changes[v.UniqueId]; ok {
|
||||
return nil
|
||||
}
|
||||
if uint64(v.Pos) > benchEnd {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_POS_NOT_VALID)
|
||||
return nil
|
||||
}
|
||||
changes[v.UniqueId] = v.Pos
|
||||
mapped.AAKDHMHCMLP = append(mapped.AAKDHMHCMLP, &pb.MHEGMHKHAAD{UniqueId: entry.MDNAGANGNKK, Pos: entry.JFCJNHNBMCB})
|
||||
}
|
||||
// Validate final positions together, so swaps need no intermediate empty slot.
|
||||
occupied := map[uint32]bool{}
|
||||
owned := map[uint32]bool{}
|
||||
active := uint32(0)
|
||||
activeAvatars := map[uint32]bool{}
|
||||
for _, role := range team.GridGameRoleList {
|
||||
owned[role.UniqueId] = true
|
||||
pos := role.Pos
|
||||
if v, ok := changes[role.UniqueId]; ok {
|
||||
pos = v
|
||||
}
|
||||
if pos != 0 {
|
||||
if occupied[pos] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_POS_EXIST_ROLE)
|
||||
return nil
|
||||
}
|
||||
occupied[pos] = true
|
||||
}
|
||||
if pos != 0 && uint64(pos) <= activeEnd {
|
||||
config, err := catalog.CapturedRoleVariant(role.Id, role.RoleStar)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if activeAvatars[config.Config.AvatarID] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_SAME_ROLE_IN_BATTLE)
|
||||
return nil
|
||||
}
|
||||
activeAvatars[config.Config.AvatarID] = true
|
||||
active++
|
||||
}
|
||||
result := &pb.GridFightUpdatePosScRsp{}
|
||||
err := cwUpdatePositions(s, mapped, result)
|
||||
rsp.Retcode = result.Retcode
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func cwUpdatePositions(s *Session, req *pb.GridFightUpdatePosCsReq, rsp *pb.GridFightUpdatePosScRsp) error {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_PARAM_NOT_MATCH)
|
||||
if _, active := CURRENT_BATTLE.Load(s.Token); active {
|
||||
PacketLog("CW_UPDATE_POS rejected reason=battle_active")
|
||||
return nil
|
||||
}
|
||||
catalog, err := common.LoadCurrencyWarsCatalog()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, revision, err := readCurrencyWarsData(catalog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if data == nil || data.DHFOFLFCLAH == nil {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_NOT_IN_GAMEPLAY)
|
||||
return nil
|
||||
}
|
||||
if revision != s.currencyWarsRevision {
|
||||
return nil
|
||||
}
|
||||
run := data.DHFOFLFCLAH
|
||||
if run.FMIGOKIDKJL != nil || len(req.AAKDHMHCMLP) == 0 {
|
||||
PacketLog("CW_UPDATE_POS rejected reason=not_preparing_or_empty")
|
||||
return nil
|
||||
}
|
||||
player, team, _ := cwComponents(run)
|
||||
if player == nil || team == nil {
|
||||
return nil
|
||||
}
|
||||
front, err := catalog.IntegerRule("GridFight_Front_AvatarMaxNum")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
back, err := catalog.IntegerRule("GridFight_Back_AvatarMaxNum")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
activeEnd := uint64(front + back)
|
||||
overflow, err := catalog.IntegerRule("GridFight_Bench_OverFlow_AvatarNum")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
benchEnd := activeEnd + uint64(player.MICEOJBAKGN) + uint64(overflow)
|
||||
changes := map[uint32]uint32{}
|
||||
for _, v := range req.AAKDHMHCMLP {
|
||||
if v == nil || v.UniqueId == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, forge := range team.KCOMPKMJCMC {
|
||||
pos := forge.Pos
|
||||
if _, changed := changes[forge.UniqueId]; changed {
|
||||
return nil
|
||||
} // Projection movement needs its separately verified sync arm.
|
||||
if pos != 0 {
|
||||
if occupied[pos] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_POS_EXIST_ROLE)
|
||||
return nil
|
||||
}
|
||||
occupied[pos] = true
|
||||
}
|
||||
if _, ok := changes[v.UniqueId]; ok {
|
||||
return nil
|
||||
}
|
||||
for _, forge := range team.PMEOPPDAMLM {
|
||||
owned[forge.UniqueId] = true
|
||||
pos := forge.Pos
|
||||
if v, ok := changes[forge.UniqueId]; ok {
|
||||
pos = v
|
||||
}
|
||||
if pos == 0 || uint64(pos) <= activeEnd || uint64(pos) > benchEnd {
|
||||
return nil
|
||||
}
|
||||
if uint64(v.Pos) > benchEnd {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_POS_NOT_VALID)
|
||||
return nil
|
||||
}
|
||||
changes[v.UniqueId] = v.Pos
|
||||
}
|
||||
// Validate final positions together, so swaps need no intermediate empty slot.
|
||||
occupied := map[uint32]bool{}
|
||||
owned := map[uint32]bool{}
|
||||
active := uint32(0)
|
||||
activeAvatars := map[uint32]bool{}
|
||||
for _, role := range team.GridGameRoleList {
|
||||
owned[role.UniqueId] = true
|
||||
pos := role.Pos
|
||||
if v, ok := changes[role.UniqueId]; ok {
|
||||
pos = v
|
||||
}
|
||||
if pos != 0 {
|
||||
if occupied[pos] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_POS_EXIST_ROLE)
|
||||
return nil
|
||||
}
|
||||
occupied[pos] = true
|
||||
}
|
||||
for id := range changes {
|
||||
if !owned[id] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_ROLE_NOT_EXIST)
|
||||
if pos != 0 && uint64(pos) <= activeEnd {
|
||||
config, err := catalog.CapturedRoleVariant(role.Id, role.RoleStar)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if activeAvatars[config.Config.AvatarID] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_SAME_ROLE_IN_BATTLE)
|
||||
return nil
|
||||
}
|
||||
activeAvatars[config.Config.AvatarID] = true
|
||||
active++
|
||||
}
|
||||
if active > player.AFFCFLFIFPH {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_REGION_FULL)
|
||||
}
|
||||
for _, forge := range team.KCOMPKMJCMC {
|
||||
pos := forge.Pos
|
||||
if _, changed := changes[forge.UniqueId]; changed {
|
||||
return nil
|
||||
} // Projection movement needs its separately verified sync arm.
|
||||
if pos != 0 {
|
||||
if occupied[pos] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_POS_EXIST_ROLE)
|
||||
return nil
|
||||
}
|
||||
occupied[pos] = true
|
||||
}
|
||||
}
|
||||
for _, forge := range team.PMEOPPDAMLM {
|
||||
owned[forge.UniqueId] = true
|
||||
pos := forge.Pos
|
||||
if v, ok := changes[forge.UniqueId]; ok {
|
||||
pos = v
|
||||
}
|
||||
if pos == 0 || uint64(pos) <= activeEnd || uint64(pos) > benchEnd {
|
||||
return nil
|
||||
}
|
||||
var updates []*pb.KFNCAIHIHCM
|
||||
for _, role := range team.GridGameRoleList {
|
||||
if pos, ok := changes[role.UniqueId]; ok {
|
||||
role.Pos = pos
|
||||
updates = append(updates, &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_CFOCDALNCBP{CFOCDALNCBP: role}})
|
||||
}
|
||||
if occupied[pos] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_POS_EXIST_ROLE)
|
||||
return nil
|
||||
}
|
||||
for _, forge := range team.PMEOPPDAMLM {
|
||||
if pos, ok := changes[forge.UniqueId]; ok {
|
||||
forge.Pos = pos
|
||||
updates = append(updates, &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_FEKCPKAPHHO{FEKCPKAPHHO: forge}})
|
||||
}
|
||||
occupied[pos] = true
|
||||
}
|
||||
for id := range changes {
|
||||
if !owned[id] {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_ROLE_NOT_EXIST)
|
||||
return nil
|
||||
}
|
||||
runtime, _ := cwBonfireRuntime(catalog, run)
|
||||
cwSyncTraitComponent(catalog, run, runtime)
|
||||
if tbCat, err := common.LoadCurrencyWarsTrailblaze(); err == nil && (cwGetTrailblazeLayer(catalog, run) > 0 || (runtime != nil && runtime.Rules["TbOpened"] != 0)) {
|
||||
updates = append(updates,
|
||||
&pb.KFNCAIHIHCM{
|
||||
MNLCHEJKDHO: &pb.KFNCAIHIHCM_HKHJJCMKKJE{
|
||||
HKHJJCMKKJE: &pb.JLKCBOIFJKC{
|
||||
TraitId: cwTrailblazeTrait,
|
||||
ENPLACDLJGA: cwTrailblazeTraitEffectProto(tbCat, runtime),
|
||||
},
|
||||
}
|
||||
if active > player.AFFCFLFIFPH {
|
||||
rsp.Retcode = uint32(pb.Retcode_RET_GRID_FIGHT_REGION_FULL)
|
||||
return nil
|
||||
}
|
||||
var updates []*pb.KFNCAIHIHCM
|
||||
for _, role := range team.GridGameRoleList {
|
||||
if pos, ok := changes[role.UniqueId]; ok {
|
||||
role.Pos = pos
|
||||
updates = append(updates, &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_CFOCDALNCBP{CFOCDALNCBP: role}})
|
||||
}
|
||||
}
|
||||
for _, forge := range team.PMEOPPDAMLM {
|
||||
if pos, ok := changes[forge.UniqueId]; ok {
|
||||
forge.Pos = pos
|
||||
updates = append(updates, &pb.KFNCAIHIHCM{MNLCHEJKDHO: &pb.KFNCAIHIHCM_FEKCPKAPHHO{FEKCPKAPHHO: forge}})
|
||||
}
|
||||
}
|
||||
runtime, err := cwBonfireRuntime(catalog, run)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cwSyncTraitComponent(catalog, run, runtime)
|
||||
if tbCat, err := common.LoadCurrencyWarsTrailblaze(); err == nil && (cwGetTrailblazeLayer(catalog, run) > 0 || (runtime != nil && runtime.Rules["TbOpened"] != 0)) {
|
||||
updates = append(updates,
|
||||
&pb.KFNCAIHIHCM{
|
||||
MNLCHEJKDHO: &pb.KFNCAIHIHCM_HKHJJCMKKJE{
|
||||
HKHJJCMKKJE: &pb.JLKCBOIFJKC{
|
||||
TraitId: cwTrailblazeTrait,
|
||||
ENPLACDLJGA: cwTrailblazeTraitEffectProto(tbCat, runtime),
|
||||
},
|
||||
},
|
||||
&pb.KFNCAIHIHCM{
|
||||
MNLCHEJKDHO: &pb.KFNCAIHIHCM_GOOCHGKBIPN{
|
||||
GOOCHGKBIPN: cwTrailblazeModifierProto(tbCat, runtime),
|
||||
},
|
||||
},
|
||||
&pb.KFNCAIHIHCM{
|
||||
MNLCHEJKDHO: &pb.KFNCAIHIHCM_GOOCHGKBIPN{
|
||||
GOOCHGKBIPN: cwTrailblazeModifierProto(tbCat, runtime),
|
||||
},
|
||||
)
|
||||
}
|
||||
if err = s.saveCurrencyWarsDataWithRuntime(data, catalog, runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = cwSend(s, cwNotify(updates...)); err != nil {
|
||||
return err
|
||||
}
|
||||
rsp.AAKDHMHCMLP = req.AAKDHMHCMLP
|
||||
rsp.Retcode = 0
|
||||
PacketLog(fmt.Sprintf("CW_UPDATE_POS saved count=%d active=%d revision=%d", len(changes), active, s.currencyWarsRevision))
|
||||
return nil
|
||||
})
|
||||
|
||||
// CmdID 8543 (GEBBMDCOLCH) -> ScRsp 8630 (ALNFEBKHCFC)
|
||||
// Protocol revision: 4.6.53 (upstream_cmdids.go).
|
||||
// Assumption: Native Client sends GEBBMDCOLCH during preparation / round transition to sync
|
||||
// the batch formation role positions (CONJCEMAHGN: MDNAGANGNKK = role UID, JFCJNHNBMCB = pos).
|
||||
// Acknowledging with retcode 0 unblocks the Client UI input controller.
|
||||
cwHandleNamed("GEBBMDCOLCH", "ALNFEBKHCFC", func(s *Session, req *pb.GEBBMDCOLCH, rsp *pb.ALNFEBKHCFC) error {
|
||||
catalog, err := common.LoadCurrencyWarsCatalog()
|
||||
if err != nil {
|
||||
rsp.Retcode = 0
|
||||
return nil
|
||||
}
|
||||
data, _, err := readCurrencyWarsData(catalog)
|
||||
if err != nil || data == nil || data.DHFOFLFCLAH == nil {
|
||||
rsp.Retcode = 0
|
||||
return nil
|
||||
}
|
||||
run := data.DHFOFLFCLAH
|
||||
_, team, _ := cwComponents(run)
|
||||
if team != nil && len(req.CONJCEMAHGN) > 0 {
|
||||
posMap := make(map[uint32]uint32, len(req.CONJCEMAHGN))
|
||||
for _, entry := range req.CONJCEMAHGN {
|
||||
if entry != nil && entry.MDNAGANGNKK != 0 {
|
||||
posMap[entry.MDNAGANGNKK] = entry.JFCJNHNBMCB
|
||||
}
|
||||
}
|
||||
changed := false
|
||||
for _, role := range team.GridGameRoleList {
|
||||
if newPos, ok := posMap[role.UniqueId]; ok && role.Pos != newPos {
|
||||
role.Pos = newPos
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
runtime, _ := cwBonfireRuntime(catalog, run)
|
||||
cwSyncTraitComponent(catalog, run, runtime)
|
||||
_ = s.saveCurrencyWarsDataWithRuntime(data, catalog, runtime)
|
||||
}
|
||||
}
|
||||
rsp.Retcode = 0
|
||||
PacketLog(fmt.Sprintf("CW_BATCH_UPDATE_POS count=%d revision=%d", len(req.CONJCEMAHGN), s.currencyWarsRevision))
|
||||
return nil
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
if err = s.saveCurrencyWarsDataWithRuntime(data, catalog, runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = cwSend(s, cwNotify(updates...)); err != nil {
|
||||
return err
|
||||
}
|
||||
rsp.AAKDHMHCMLP = req.AAKDHMHCMLP
|
||||
rsp.Retcode = 0
|
||||
PacketLog(fmt.Sprintf("CW_UPDATE_POS saved count=%d active=%d revision=%d", len(changes), active, s.currencyWarsRevision))
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user