This commit is contained in:
269
modules/player/service/pet_fusion_tx.go
Normal file
269
modules/player/service/pet_fusion_tx.go
Normal file
@@ -0,0 +1,269 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/cool"
|
||||
baseservice "blazing/modules/base/service"
|
||||
"blazing/modules/player/model"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var (
|
||||
errPetFusionInsufficientItems = errors.New("pet fusion insufficient items")
|
||||
errPetFusionPetNotFound = errors.New("pet fusion pet not found")
|
||||
errPetFusionPlayerNotFound = errors.New("pet fusion player not found")
|
||||
)
|
||||
|
||||
type PetFusionTxResult struct {
|
||||
NewPet *model.PetInfo
|
||||
CostItemUsed bool
|
||||
UpdatedAux *model.PetInfo
|
||||
}
|
||||
|
||||
func (s *UserService) PetFusionTx(
|
||||
currentInfo model.PlayerInfo,
|
||||
masterCatchTime uint32,
|
||||
auxCatchTime uint32,
|
||||
materialCounts map[uint32]int,
|
||||
goldItemIDs []uint32,
|
||||
keepAuxItemID uint32,
|
||||
failureItemID uint32,
|
||||
cost int64,
|
||||
newPet *model.PetInfo,
|
||||
failedAux *model.PetInfo,
|
||||
) (*PetFusionTxResult, errorcode.ErrorCode) {
|
||||
if s == nil || s.Pet == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemError
|
||||
}
|
||||
|
||||
userID := s.Pet.userid
|
||||
nextInfo := currentInfo
|
||||
if nextInfo.Coins < cost {
|
||||
return nil, errorcode.ErrorCodes.ErrSunDouInsufficient10016
|
||||
}
|
||||
nextInfo.Coins -= cost
|
||||
|
||||
result := &PetFusionTxResult{}
|
||||
err := g.DB().Transaction(context.TODO(), func(ctx context.Context, tx gdb.TX) error {
|
||||
if err := updatePlayerInfoTx(tx, userID, nextInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := consumeItemCountsTx(tx, userID, materialCounts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if newPet == nil {
|
||||
used, err := consumeOptionalItemTx(tx, userID, goldItemIDs, failureItemID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result.CostItemUsed = used
|
||||
if !used && failedAux != nil {
|
||||
if err := updatePetDataTx(tx, userID, auxCatchTime, *failedAux); err != nil {
|
||||
return err
|
||||
}
|
||||
auxCopy := *failedAux
|
||||
result.UpdatedAux = &auxCopy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := deletePetTx(tx, userID, masterCatchTime); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
used, err := consumeOptionalItemTx(tx, userID, goldItemIDs, keepAuxItemID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result.CostItemUsed = used
|
||||
if !used {
|
||||
if err := deletePetTx(tx, userID, auxCatchTime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
catchTime, err := addPetTx(tx, s.Pet, newPet, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
petCopy := *newPet
|
||||
petCopy.CatchTime = catchTime
|
||||
result.NewPet = &petCopy
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
return result, 0
|
||||
}
|
||||
|
||||
switch {
|
||||
case errors.Is(err, errPetFusionInsufficientItems):
|
||||
return nil, errorcode.ErrorCodes.ErrInsufficientItems
|
||||
case errors.Is(err, errPetFusionPetNotFound):
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotFusionReady2
|
||||
case errors.Is(err, errPetFusionPlayerNotFound):
|
||||
return nil, errorcode.ErrorCodes.ErrSystemError
|
||||
default:
|
||||
cool.Logger.Error(context.TODO(), "pet fusion tx failed", userID, err)
|
||||
return nil, errorcode.ErrorCodes.ErrSystemError
|
||||
}
|
||||
}
|
||||
|
||||
func updatePlayerInfoTx(tx gdb.TX, userID uint32, info model.PlayerInfo) error {
|
||||
res, err := tx.Model(model.NewPlayer()).Where("player_id", userID).Data("data", info).Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
affected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if affected == 0 {
|
||||
return errPetFusionPlayerNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func consumeItemCountsTx(tx gdb.TX, userID uint32, itemCounts map[uint32]int) error {
|
||||
for itemID, count := range itemCounts {
|
||||
if err := updateItemCountTx(tx, userID, itemID, -count); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func consumeOptionalItemTx(tx gdb.TX, userID uint32, itemIDs []uint32, target uint32) (bool, error) {
|
||||
for _, itemID := range itemIDs {
|
||||
if itemID != target {
|
||||
continue
|
||||
}
|
||||
if err := updateItemCountTx(tx, userID, target, -1); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func updateItemCountTx(tx gdb.TX, userID uint32, id uint32, count int) error {
|
||||
if cool.Config.ServerInfo.IsVip != 0 && count < 0 {
|
||||
return nil
|
||||
}
|
||||
if id == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
baseModel := tx.Model(model.NewPlayerBag()).
|
||||
Where("player_id", userID).
|
||||
Where("is_vip", cool.Config.ServerInfo.IsVip)
|
||||
|
||||
ok, err := baseModel.Where("item_id", id).Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ok {
|
||||
updateModel := tx.Model(model.NewPlayerBag()).
|
||||
Where("player_id", userID).
|
||||
Where("is_vip", cool.Config.ServerInfo.IsVip).
|
||||
Where("item_id", id)
|
||||
if count < 0 {
|
||||
updateModel = updateModel.Where("item_cnt + ? > 0", count)
|
||||
}
|
||||
|
||||
result, err := updateModel.Increment("item_cnt", count)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
affected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if affected == 0 {
|
||||
return errPetFusionInsufficientItems
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if count <= 0 {
|
||||
return errPetFusionInsufficientItems
|
||||
}
|
||||
|
||||
_, err = tx.Model(model.NewPlayerBag()).Data(g.Map{
|
||||
"player_id": userID,
|
||||
"item_id": id,
|
||||
"item_cnt": count,
|
||||
"is_vip": cool.Config.ServerInfo.IsVip,
|
||||
}).Insert()
|
||||
return err
|
||||
}
|
||||
|
||||
func updatePetDataTx(tx gdb.TX, userID uint32, catchTime uint32, pet model.PetInfo) error {
|
||||
res, err := tx.Model(model.NewPet()).
|
||||
Where("player_id", userID).
|
||||
Where("is_vip", cool.Config.ServerInfo.IsVip).
|
||||
Where("catch_time", catchTime).
|
||||
Data("data", pet).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
affected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if affected == 0 {
|
||||
return errPetFusionPetNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deletePetTx(tx gdb.TX, userID uint32, catchTime uint32) error {
|
||||
res, err := tx.Model(model.NewPet()).
|
||||
Where("player_id", userID).
|
||||
Where("is_vip", cool.Config.ServerInfo.IsVip).
|
||||
Where("catch_time", catchTime).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
affected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if affected == 0 {
|
||||
return errPetFusionPetNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addPetTx(tx gdb.TX, petService *PetService, petInfo *model.PetInfo, saleCount uint32) (uint32, error) {
|
||||
if petInfo == nil {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
catchTime, err := petService.nextCatchTime(tx.Model(baseservice.NewBaseSysUserService().Model))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
petCopy := *petInfo
|
||||
petCopy.CatchTime = catchTime
|
||||
playerPet := model.Pet{
|
||||
PlayerID: petService.userid,
|
||||
Data: petCopy,
|
||||
CatchTime: catchTime,
|
||||
Free: 0,
|
||||
SaleCount: saleCount,
|
||||
}
|
||||
playerPet.IsVip = cool.Config.ServerInfo.IsVip
|
||||
if _, err := tx.Model(model.NewPet()).Insert(playerPet); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return catchTime, nil
|
||||
}
|
||||
Reference in New Issue
Block a user