fix: 修复战斗动作提交逻辑

This commit is contained in:
xinian
2026-04-03 00:02:34 +08:00
committed by cnb
parent 43881fd988
commit c19ee7de03
4 changed files with 52 additions and 211 deletions

View File

@@ -1,181 +1,28 @@
package controller
import (
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode"
"blazing/logic/service/fight"
"blazing/logic/service/pet"
"blazing/logic/service/player"
"blazing/modules/player/model"
)
func buildPetShortInfo(info model.PetInfo) pet.PetShortInfo {
return pet.PetShortInfo{
ID: info.ID,
CatchTime: info.CatchTime,
Level: info.Level,
SkinID: info.SkinID,
ShinyLen: info.ShinyLen,
ShinyInfo: info.ShinyInfo,
}
}
func buildPetListOutboundInfo(petList []model.PetInfo) *pet.GetPetListOutboundInfo {
result := &pet.GetPetListOutboundInfo{
ShortInfoList: make([]pet.PetShortInfo, len(petList)),
}
for i := range petList {
result.ShortInfoList[i] = buildPetShortInfo(petList[i])
}
return result
}
func removePetByCatchTime(petList []model.PetInfo, catchTime uint32) []model.PetInfo {
for i := range petList {
if petList[i].CatchTime == catchTime {
return append(petList[:i], petList[i+1:]...)
}
}
return petList
}
func buildWarehousePetList(player *player.Player) []model.PetInfo {
allPets := player.Service.Pet.PetInfo(0)
if len(allPets) == 0 {
return make([]model.PetInfo, 0)
}
usedCatchTimes := make(map[uint32]struct{}, len(player.Info.PetList)+len(player.Info.BackupPetList))
for _, petInfo := range player.Info.PetList {
usedCatchTimes[petInfo.CatchTime] = struct{}{}
}
for _, petInfo := range player.Info.BackupPetList {
usedCatchTimes[petInfo.CatchTime] = struct{}{}
}
result := make([]model.PetInfo, 0, len(allPets))
for i := range allPets {
catchTime := allPets[i].Data.CatchTime
if _, exists := usedCatchTimes[catchTime]; exists {
continue
}
result = append(result, allPets[i].Data)
}
return result
}
func findBackupPet(player *player.Player, catchTime uint32) (int, *model.PetInfo, bool) {
for i := range player.Info.BackupPetList {
if player.Info.BackupPetList[i].CatchTime == catchTime {
return i, &player.Info.BackupPetList[i], true
}
}
return -1, nil, false
}
func syncBackupPetList(player *player.Player) {
if player.Info.BackupPetList == nil {
player.Info.BackupPetList = make([]model.PetInfo, 0)
return
}
bagPets := player.Service.Pet.PetInfo(0)
if len(bagPets) == 0 {
player.Info.BackupPetList = make([]model.PetInfo, 0)
return
}
bagCatchTimes := make(map[uint32]struct{}, len(bagPets))
for i := range bagPets {
bagCatchTimes[bagPets[i].Data.CatchTime] = struct{}{}
}
mainPetCatchTimes := make(map[uint32]struct{}, len(player.Info.PetList))
for _, petInfo := range player.Info.PetList {
mainPetCatchTimes[petInfo.CatchTime] = struct{}{}
}
nextBackupList := make([]model.PetInfo, 0, len(player.Info.BackupPetList))
for _, petInfo := range player.Info.BackupPetList {
if _, inBag := bagCatchTimes[petInfo.CatchTime]; !inBag {
continue
}
if _, inMain := mainPetCatchTimes[petInfo.CatchTime]; inMain {
continue
}
nextBackupList = append(nextBackupList, petInfo)
}
player.Info.BackupPetList = nextBackupList
}
func buildUserBagPetInfo(player *player.Player) *pet.GetUserBagPetInfoOutboundInfo {
syncBackupPetList(player)
result := &pet.GetUserBagPetInfoOutboundInfo{
PetList: make([]model.PetInfo, len(player.Info.PetList)),
BackupPetList: make([]model.PetInfo, len(player.Info.BackupPetList)),
}
copy(result.PetList, player.Info.PetList)
copy(result.BackupPetList, player.Info.BackupPetList)
return result
}
func buildOrderedPetList(
catchTimes []uint32,
petMap map[uint32]model.PetInfo,
used map[uint32]struct{},
) ([]model.PetInfo, bool) {
result := make([]model.PetInfo, 0, len(catchTimes))
for _, catchTime := range catchTimes {
if catchTime == 0 {
return nil, false
}
if _, exists := used[catchTime]; exists {
return nil, false
}
petInfo, exists := petMap[catchTime]
if !exists {
return nil, false
}
used[catchTime] = struct{}{}
result = append(result, petInfo)
}
return result, true
}
func buildPetShowOutboundInfo(userID, flag uint32, info *model.PetInfo) *pet.PetShowOutboundInfo {
return &pet.PetShowOutboundInfo{
UserID: userID,
CatchTime: info.CatchTime,
ID: info.ID,
Flag: flag,
Dv: info.Dv,
ShinyLen: info.ShinyLen,
ShinyInfo: info.ShinyInfo,
SkinID: info.SkinID,
}
}
// GetPetInfo 获取精灵信息
// data: 包含精灵捕获时间的输入信息
// player: 当前玩家对象
// 返回: 精灵信息和错误码
func (h Controller) GetPetInfo(
data *pet.InInfo,
player *player.Player) (result *model.PetInfo,
err errorcode.ErrorCode) {
_, petInfo, found := player.FindPet(data.CatchTime)
if found {
result = petInfo
return result, 0
}
ret := player.Service.Pet.PetInfoOneByCatchTime(data.CatchTime)
if ret == nil {
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
result = &ret.Data
return result, 0
}
@@ -188,56 +35,7 @@ func (h Controller) GetUserBagPetInfo(
return buildUserBagPetInfo(player), 0
}
// GetPetList 获取仓库列表
// data: 空输入结构
// player: 当前玩家对象
// 返回: 精灵列表和错误码
// SavePetBagOrder 保存当前主背包和备用背包顺序
func (h Controller) SavePetBagOrder(
data *pet.SavePetBagOrderInboundInfo,
player *player.Player) (result *fight.NullOutboundInfo,
err errorcode.ErrorCode) {
syncBackupPetList(player)
if len(data.PetList) > 6 || len(data.BackupPetList) > 6 {
return nil, errorcode.ErrorCodes.ErrPokemonIDMismatch
}
totalPetCount := len(player.Info.PetList) + len(player.Info.BackupPetList)
if len(data.PetList)+len(data.BackupPetList) != totalPetCount {
return nil, errorcode.ErrorCodes.ErrPokemonIDMismatch
}
petMap := make(map[uint32]model.PetInfo, totalPetCount)
for _, petInfo := range player.Info.PetList {
petMap[petInfo.CatchTime] = petInfo
}
for _, petInfo := range player.Info.BackupPetList {
petMap[petInfo.CatchTime] = petInfo
}
used := make(map[uint32]struct{}, totalPetCount)
battleList, ok := buildOrderedPetList(data.PetList, petMap, used)
if !ok {
return nil, errorcode.ErrorCodes.ErrPokemonIDMismatch
}
backupList, ok := buildOrderedPetList(data.BackupPetList, petMap, used)
if !ok {
return nil, errorcode.ErrorCodes.ErrPokemonIDMismatch
}
if len(used) != totalPetCount {
return nil, errorcode.ErrorCodes.ErrPokemonIDMismatch
}
player.Info.PetList = battleList
player.Info.BackupPetList = backupList
player.Service.Info.Save(*player.Info)
return nil, 0
}
// GetPetList 获取当前主背包列表
func (h Controller) GetPetList(
data *pet.GetPetListInboundEmpty,
player *player.Player) (result *pet.GetPetListOutboundInfo,
@@ -245,10 +43,7 @@ func (h Controller) GetPetList(
return buildPetListOutboundInfo(player.Info.PetList), 0
}
// GetPetReleaseList 获取放生列表
// data: 空输入结构
// player: 当前玩家对象
// 返回: 放生精灵列表和错误码
// GetPetReleaseList 获取仓库可放生列表
func (h Controller) GetPetReleaseList(
data *pet.GetPetListFreeInboundEmpty,
player *player.Player) (result *pet.GetPetListOutboundInfo,
@@ -257,6 +52,7 @@ func (h Controller) GetPetReleaseList(
return buildPetListOutboundInfo(buildWarehousePetList(player)), 0
}
<<<<<<< ours
// PetReleaseToWarehouse 将精灵从仓库包中放生
// data: 包含精灵ID和捕获时间的输入信息
// player: 当前玩家对象
@@ -432,16 +228,18 @@ func (h Controller) TogglePetBagWarehouseLegacy(
return result, 0
}
=======
>>>>>>> theirs
// PlayerShowPet 精灵展示
func (h Controller) PlayerShowPet(
data *pet.PetShowInboundInfo, player *player.Player) (result *pet.PetShowOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
data *pet.PetShowInboundInfo, player *player.Player) (result *pet.PetShowOutboundInfo, err errorcode.ErrorCode) {
result = &pet.PetShowOutboundInfo{
UserID: data.Head.UserID,
CatchTime: data.CatchTime,
Flag: data.Flag,
}
_, currentPet, ok := player.FindPet(data.CatchTime)
_, currentPet, ok := player.FindPet(data.CatchTime)
if data.Flag == 0 {
player.SetPetDisplay(0, nil)
player.GetSpace().RefreshUserInfo(player)
@@ -458,6 +256,7 @@ func (h Controller) PlayerShowPet(
result = buildPetShowOutboundInfo(data.Head.UserID, data.Flag, currentPet)
defer player.GetSpace().Broadcast(player, data.Head.CMD, result)
return
<<<<<<< ours
}
@@ -511,4 +310,6 @@ func (h Controller) SetPetExp(data *pet.PetSetExpInboundInfo, player *player.Pla
}
return &pet.PetSetExpOutboundInfo{Exp: player.Info.ExpPool}, errorcode.ErrorCodes.ErrSystemError
=======
>>>>>>> theirs
}

View File

@@ -6,6 +6,10 @@ import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/modules/player/model"
<<<<<<< ours
=======
"context"
>>>>>>> theirs
"github.com/jinzhu/copier"
)
@@ -44,6 +48,17 @@ func (f *FightC) submitAction(act action.BattleActionI) {
return
}
<<<<<<< ours
=======
round := f.actionRound.Load()
if round == 0 {
cool.Logger.Printf(context.Background(), logMsg, userID, targetID)
return
}
act.SetRound(round)
>>>>>>> theirs
f.actionMu.Lock()
if !f.acceptActions {
f.actionMu.Unlock()
@@ -75,6 +90,7 @@ func (f *FightC) submitAction(act action.BattleActionI) {
default:
}
}
<<<<<<< ours
func (f *FightC) nextAction() action.BattleActionI {
f.actionMu.Lock()
@@ -82,6 +98,8 @@ func (f *FightC) nextAction() action.BattleActionI {
f.actionMu.Unlock()
return nil
}
=======
>>>>>>> theirs
act := f.pendingActions[0]
copy(f.pendingActions, f.pendingActions[1:])
@@ -200,12 +218,21 @@ func (f *FightC) UseItem(c common.PlayerI, cacthid, itemid uint32) {
return
}
<<<<<<< ours
=======
>>>>>>> theirs
if f.Info.Mode == info.BattleMode.PET_MELEE {
go f.UseSkill(c, 0)
return
}
<<<<<<< ours
f.submitAction(&action.UseItemAction{BaseAction: action.NewBaseAction(c.GetInfo().UserID), ItemID: itemid, CacthTime: cacthid})
=======
f.submitAction(&action.UseItemAction{BaseAction: action.NewBaseAction(c.GetInfo().UserID), ItemID: itemid, CacthTime: cacthid},
"action round is not ready, failed to send UseItem, userID: %d, skillID: %d",
c.GetInfo().UserID, cacthid)
>>>>>>> theirs
}
// ReadyFight 处理玩家战斗准备逻辑,当满足条件时启动战斗循环

View File

@@ -319,6 +319,7 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction)
FAttack: *f.First.AttackValue,
SAttack: *f.Second.AttackValue,
}
f.actionRound.Store(uint32(f.Round + 1))
//因为切完才能广播,所以必须和回合结束分开结算
f.Broadcast(func(fighter *input.Input) {
for _, switchAction := range f.Switch {

View File

@@ -36,6 +36,7 @@ type FightC struct {
acceptActions bool
pendingActions []action.BattleActionI // 待处理动作队列,同一玩家最多保留两段动作
<<<<<<< ours
quit chan struct{}
over chan struct{}
First *input.Input
@@ -44,6 +45,17 @@ type FightC struct {
closefight bool
overl sync.Once
waittime int
=======
quit chan struct{}
over chan struct{}
First *input.Input
TrueFirst *input.Input
Second *input.Input
closefight bool
overl sync.Once
waittime int
actionRound atomic.Uint32
>>>>>>> theirs
model.FightOverInfo
//战斗结束的插装
callback func(model.FightOverInfo)