refactor: 重构宠物背包逻辑到玩家服务
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful

This commit is contained in:
xinian
2026-04-05 05:47:25 +08:00
committed by cnb
parent bceb7965f7
commit e71971d0b4
7 changed files with 175 additions and 192 deletions

View File

@@ -12,35 +12,9 @@ func (h Controller) SavePetBagOrder(
data *pet.SavePetBagOrderInboundInfo, data *pet.SavePetBagOrderInboundInfo,
player *player.Player) (result *fight.NullOutboundInfo, player *player.Player) (result *fight.NullOutboundInfo,
err errorcode.ErrorCode) { err errorcode.ErrorCode) {
if !player.SavePetBagOrder(data.PetList, data.BackupPetList) {
if len(data.PetList) > 6 || len(data.BackupPetList) > 6 {
return nil, errorcode.ErrorCodes.ErrPokemonIDMismatch 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 := buildPetInfoMap(player.Info.PetList, player.Info.BackupPetList)
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) player.Service.Info.Save(*player.Info)
return nil, 0 return nil, 0
} }
@@ -48,7 +22,7 @@ func (h Controller) SavePetBagOrder(
// PetRetrieveFromWarehouse 领回仓库精灵 // PetRetrieveFromWarehouse 领回仓库精灵
func (h Controller) PetRetrieveFromWarehouse( func (h Controller) PetRetrieveFromWarehouse(
data *pet.PET_RETRIEVE, player *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { data *pet.PET_RETRIEVE, player *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
if _, ok := findPetListSlot(player, data.CatchTime); ok { if _, ok := player.FindPetBagSlot(data.CatchTime); ok {
return nil, 0 return nil, 0
} }
@@ -57,13 +31,7 @@ func (h Controller) PetRetrieveFromWarehouse(
return nil, 0 return nil, 0
} }
if len(player.Info.PetList) < 6 { player.AddPetToAvailableBag(petInfo.Data)
player.Info.PetList = append(player.Info.PetList, petInfo.Data)
} else if len(player.Info.BackupPetList) < 6 {
player.Info.BackupPetList = append(player.Info.BackupPetList, petInfo.Data)
}
return nil, 0 return nil, 0
} }
@@ -82,19 +50,19 @@ func (h Controller) TogglePetBagWarehouse(
switch data.Flag { switch data.Flag {
case 0: case 0:
slot, ok := findPetListSlot(player, data.CatchTime) slot, ok := player.FindPetBagSlot(data.CatchTime)
if !ok { if !ok {
return result, errorcode.ErrorCodes.ErrPokemonNotExists return result, errorcode.ErrorCodes.ErrPokemonNotExists
} }
if !slot.isValid() { if !slot.IsValid() {
return result, errorcode.ErrorCodes.ErrPokemonIDMismatch return result, errorcode.ErrorCodes.ErrPokemonIDMismatch
} }
if !player.Service.Pet.Update(slot.info) { if !player.Service.Pet.Update(slot.PetInfo()) {
return result, errorcode.ErrorCodes.ErrSystemError return result, errorcode.ErrorCodes.ErrSystemError
} }
slot.remove() slot.Remove()
if slot.kind == petListKindMain { if slot.IsMainBag() {
player.Service.Info.Save(*player.Info) player.Service.Info.Save(*player.Info)
} }
@@ -102,7 +70,7 @@ func (h Controller) TogglePetBagWarehouse(
if len(player.Info.PetList) >= 6 && len(player.Info.BackupPetList) >= 6 { if len(player.Info.PetList) >= 6 && len(player.Info.BackupPetList) >= 6 {
return result, errorcode.ErrorCodes.ErrPokemonIDMismatch return result, errorcode.ErrorCodes.ErrPokemonIDMismatch
} }
if _, ok := findPetListSlot(player, data.CatchTime); ok { if _, ok := player.FindPetBagSlot(data.CatchTime); ok {
return result, 0 return result, 0
} }
@@ -110,11 +78,7 @@ func (h Controller) TogglePetBagWarehouse(
if petInfo == nil { if petInfo == nil {
return result, errorcode.ErrorCodes.ErrPokemonNotExists return result, errorcode.ErrorCodes.ErrPokemonNotExists
} }
if len(player.Info.PetList) < 6 { player.AddPetToAvailableBag(petInfo.Data)
player.Info.PetList = append(player.Info.PetList, petInfo.Data)
} else {
player.Info.BackupPetList = append(player.Info.BackupPetList, petInfo.Data)
}
result.PetInfo = petInfo.Data result.PetInfo = petInfo.Data
} }
@@ -151,7 +115,7 @@ func (h Controller) TogglePetBagWarehouseLegacy(
} }
player.Info.PetList = append(player.Info.PetList[:index], player.Info.PetList[index+1:]...) player.Info.PetList = append(player.Info.PetList[:index], player.Info.PetList[index+1:]...)
player.Info.BackupPetList = removePetByCatchTime(player.Info.BackupPetList, data.CatchTime) player.RemoveBackupPet(data.CatchTime)
player.Info.BackupPetList = append(player.Info.BackupPetList, *currentPet) player.Info.BackupPetList = append(player.Info.BackupPetList, *currentPet)
case 1: case 1:
@@ -160,11 +124,11 @@ func (h Controller) TogglePetBagWarehouseLegacy(
} }
if _, _, ok := player.FindPet(data.CatchTime); ok { if _, _, ok := player.FindPet(data.CatchTime); ok {
player.Info.BackupPetList = removePetByCatchTime(player.Info.BackupPetList, data.CatchTime) player.RemoveBackupPet(data.CatchTime)
break break
} }
if index, backupPet, ok := findBackupPet(player, data.CatchTime); ok { if index, backupPet, ok := player.FindBackupPet(data.CatchTime); ok {
if index < 0 || index >= len(player.Info.BackupPetList) { if index < 0 || index >= len(player.Info.BackupPetList) {
return result, errorcode.ErrorCodes.ErrPokemonIDMismatch return result, errorcode.ErrorCodes.ErrPokemonIDMismatch
} }

View File

@@ -101,7 +101,7 @@ func (h Controller) PetFusion(data *pet.C2S_PetFusion, c *player.Player) (result
} }
c.Service.Pet.PetAdd(newPet, 0) c.Service.Pet.PetAdd(newPet, 0)
println(c.Info.UserID, "进行融合", len(c.Info.PetList), masterPet.ID, auxPet.ID, newPet.ID) //println(c.Info.UserID, "进行融合", len(c.Info.PetList), masterPet.ID, auxPet.ID, newPet.ID)
c.PetDel(data.Mcatchtime) c.PetDel(data.Mcatchtime)
if useOptionalItem(c, data.GoldItem1[:], petFusionKeepAuxItemID) { if useOptionalItem(c, data.GoldItem1[:], petFusionKeepAuxItemID) {

View File

@@ -33,12 +33,16 @@ func (h Controller) GetUserBagPetInfo(
data *pet.GetUserBagPetInfoInboundEmpty, data *pet.GetUserBagPetInfoInboundEmpty,
player *player.Player) (result *pet.GetUserBagPetInfoOutboundInfo, player *player.Player) (result *pet.GetUserBagPetInfoOutboundInfo,
err errorcode.ErrorCode) { err errorcode.ErrorCode) {
return buildUserBagPetInfo(player), 0 return player.GetUserBagPetInfo(), 0
}
type GetPetListInboundEmpty struct {
Head common.TomeeHeader `cmd:"2303" struc:"skip"`
} }
// GetPetList 获取当前主背包列表 // GetPetList 获取当前主背包列表
func (h Controller) GetPetList( func (h Controller) GetPetList(
data *pet.GetPetListInboundEmpty, data *GetPetListInboundEmpty,
player *player.Player) (result *pet.GetPetListOutboundInfo, player *player.Player) (result *pet.GetPetListOutboundInfo,
err errorcode.ErrorCode) { err errorcode.ErrorCode) {
return buildPetListOutboundInfo(player.Info.PetList), 0 return buildPetListOutboundInfo(player.Info.PetList), 0

View File

@@ -2,32 +2,9 @@ package controller
import ( import (
"blazing/logic/service/pet" "blazing/logic/service/pet"
"blazing/logic/service/player"
"blazing/modules/player/model" "blazing/modules/player/model"
) )
type petListKind uint8
const (
petListKindMain petListKind = iota
petListKindBackup
)
type petListSlot struct {
list *[]model.PetInfo
index int
info model.PetInfo
kind petListKind
}
func (slot petListSlot) isValid() bool {
return slot.list != nil && slot.index >= 0 && slot.index < len(*slot.list)
}
func (slot petListSlot) remove() {
*slot.list = append((*slot.list)[:slot.index], (*slot.list)[slot.index+1:]...)
}
func buildPetShortInfo(info model.PetInfo) pet.PetShortInfo { func buildPetShortInfo(info model.PetInfo) pet.PetShortInfo {
return pet.PetShortInfo{ return pet.PetShortInfo{
ID: info.ID, ID: info.ID,
@@ -49,114 +26,6 @@ func buildPetListOutboundInfo(petList []model.PetInfo) *pet.GetPetListOutboundIn
return result 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 buildCatchTimeSet(petLists ...[]model.PetInfo) map[uint32]struct{} {
total := 0
for _, petList := range petLists {
total += len(petList)
}
catchTimes := make(map[uint32]struct{}, total)
for _, petList := range petLists {
for _, petInfo := range petList {
catchTimes[petInfo.CatchTime] = struct{}{}
}
}
return catchTimes
}
func buildPetInfoMap(petLists ...[]model.PetInfo) map[uint32]model.PetInfo {
total := 0
for _, petList := range petLists {
total += len(petList)
}
petMap := make(map[uint32]model.PetInfo, total)
for _, petList := range petLists {
for _, petInfo := range petList {
petMap[petInfo.CatchTime] = petInfo
}
}
return petMap
}
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 findPetListSlot(player *player.Player, catchTime uint32) (petListSlot, bool) {
if index, petInfo, ok := player.FindPet(catchTime); ok {
return petListSlot{
list: &player.Info.PetList,
index: index,
info: *petInfo,
kind: petListKindMain,
}, true
}
if index, petInfo, ok := findBackupPet(player, catchTime); ok {
return petListSlot{
list: &player.Info.BackupPetList,
index: index,
info: *petInfo,
kind: petListKindBackup,
}, true
}
return petListSlot{}, false
}
func buildUserBagPetInfo(player *player.Player) *pet.GetUserBagPetInfoOutboundInfo {
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 { func buildPetShowOutboundInfo(userID, flag uint32, info *model.PetInfo) *pet.PetShowOutboundInfo {
return &pet.PetShowOutboundInfo{ return &pet.PetShowOutboundInfo{
UserID: userID, UserID: userID,

View File

@@ -12,7 +12,7 @@ import (
func (h Controller) PetReleaseToWarehouse( func (h Controller) PetReleaseToWarehouse(
data *pet.PET_ROWEI, player *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { data *pet.PET_ROWEI, player *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
_, _, inBag := player.FindPet(data.CatchTime) _, _, inBag := player.FindPet(data.CatchTime)
_, _, inBackup := findBackupPet(player, data.CatchTime) _, _, inBackup := player.FindBackupPet(data.CatchTime)
freeForbidden := xmlres.PetMAP[int(data.ID)].FreeForbidden freeForbidden := xmlres.PetMAP[int(data.ID)].FreeForbidden
if inBag || inBackup || freeForbidden == 1 { if inBag || inBackup || freeForbidden == 1 {
return nil, errorcode.ErrorCodes.ErrCannotReleaseNonWarehouse return nil, errorcode.ErrorCodes.ErrCannotReleaseNonWarehouse

View File

@@ -6,10 +6,6 @@ import (
"blazing/modules/player/model" "blazing/modules/player/model"
) )
type GetPetListInboundEmpty struct {
Head common.TomeeHeader `cmd:"2303" struc:"skip"`
}
type GetPetListOutboundInfo struct { type GetPetListOutboundInfo struct {
ShortInfoListLen uint32 `struc:"int32,sizeof=ShortInfoList"` ShortInfoListLen uint32 `struc:"int32,sizeof=ShortInfoList"`
ShortInfoList []PetShortInfo ShortInfoList []PetShortInfo

View File

@@ -1,10 +1,34 @@
package player package player
import ( import (
"blazing/common/utils"
"blazing/logic/service/pet" "blazing/logic/service/pet"
"blazing/modules/player/model" "blazing/modules/player/model"
) )
type PetBagSlot struct {
list *[]model.PetInfo
index int
info model.PetInfo
main bool
}
func (slot PetBagSlot) IsValid() bool {
return slot.list != nil && slot.index >= 0 && slot.index < len(*slot.list)
}
func (slot PetBagSlot) Remove() {
*slot.list = append((*slot.list)[:slot.index], (*slot.list)[slot.index+1:]...)
}
func (slot PetBagSlot) PetInfo() model.PetInfo {
return slot.info
}
func (slot PetBagSlot) IsMainBag() bool {
return slot.main
}
func buildCatchTimeSet(petLists ...[]model.PetInfo) map[uint32]struct{} { func buildCatchTimeSet(petLists ...[]model.PetInfo) map[uint32]struct{} {
total := 0 total := 0
for _, petList := range petLists { for _, petList := range petLists {
@@ -20,14 +44,140 @@ func buildCatchTimeSet(petLists ...[]model.PetInfo) map[uint32]struct{} {
return catchTimes return catchTimes
} }
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 buildPetInfoMap(petLists ...[]model.PetInfo) map[uint32]model.PetInfo {
total := 0
for _, petList := range petLists {
total += len(petList)
}
petMap := make(map[uint32]model.PetInfo, total)
for _, petList := range petLists {
for _, petInfo := range petList {
petMap[petInfo.CatchTime] = petInfo
}
}
return petMap
}
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
}
// GetUserBagPetInfo 返回主背包和并列备用精灵列表。 // GetUserBagPetInfo 返回主背包和并列备用精灵列表。
func (p *Player) GetUserBagPetInfo() *pet.GetUserBagPetInfoOutboundInfo { func (p *Player) GetUserBagPetInfo() *pet.GetUserBagPetInfoOutboundInfo {
result := &pet.GetUserBagPetInfoOutboundInfo{ result := &pet.GetUserBagPetInfoOutboundInfo{
PetList: make([]model.PetInfo, len(p.Info.PetList)), PetList: p.Info.PetList,
BackupPetList: make([]model.PetInfo, len(p.Info.BackupPetList)), BackupPetList: p.Info.BackupPetList,
} }
copy(result.PetList, p.Info.PetList)
copy(result.BackupPetList, p.Info.BackupPetList)
return result return result
} }
func (p *Player) FindBackupPet(catchTime uint32) (int, *model.PetInfo, bool) {
return utils.FindWithIndex(p.Info.BackupPetList, func(petInfo model.PetInfo) bool {
return petInfo.CatchTime == catchTime
})
}
func (p *Player) FindPetBagSlot(catchTime uint32) (PetBagSlot, bool) {
if index, petInfo, ok := p.FindPet(catchTime); ok {
return PetBagSlot{
list: &p.Info.PetList,
index: index,
info: *petInfo,
main: true,
}, true
}
if index, petInfo, ok := p.FindBackupPet(catchTime); ok {
return PetBagSlot{
list: &p.Info.BackupPetList,
index: index,
info: *petInfo,
main: false,
}, true
}
return PetBagSlot{}, false
}
func (p *Player) AddPetToAvailableBag(petInfo model.PetInfo) bool {
if len(p.Info.PetList) < 6 {
p.Info.PetList = append(p.Info.PetList, petInfo)
return true
}
if len(p.Info.BackupPetList) < 6 {
p.Info.BackupPetList = append(p.Info.BackupPetList, petInfo)
return true
}
return false
}
func (p *Player) RemoveBackupPet(catchTime uint32) {
p.Info.BackupPetList = removePetByCatchTime(p.Info.BackupPetList, catchTime)
}
func (p *Player) SavePetBagOrder(petList []uint32, backupPetList []uint32) bool {
if len(petList) > 6 || len(backupPetList) > 6 {
return false
}
totalPetCount := len(p.Info.PetList) + len(p.Info.BackupPetList)
if len(petList)+len(backupPetList) != totalPetCount {
return false
}
petMap := buildPetInfoMap(p.Info.PetList, p.Info.BackupPetList)
used := make(map[uint32]struct{}, totalPetCount)
battleList, ok := buildOrderedPetList(petList, petMap, used)
if !ok {
return false
}
backupList, ok := buildOrderedPetList(backupPetList, petMap, used)
if !ok {
return false
}
if len(used) != totalPetCount {
return false
}
p.Info.PetList = battleList
p.Info.BackupPetList = backupList
return true
}