Files
bl/logic/service/fight/input.go
昔念 dffd6a63a6
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(player): 优化客户端数据处理机制

重构ClientData的消息处理流程,将OnEvent方法改为非阻塞的通道投递模式,
新增MsgChan用于异步消息传递,避免eventloop阻塞问题。

fix(fight): 修复宠物闪光属性过滤条件

在initplayer方法中增加color.Alpha不为0的判断条件,确保只有有效的
闪光属性才会被添加到宠物信息中。

refactor(socket): 调整服务器事件处理逻辑

移除未使用的Lockfree库依赖,注释掉不再需要的连接关闭资源释放代码,
调整事件处理的工作池提交逻辑。

feat(rpc): 新增Redis发布功能

为RPC_player添加SendPackCmd方法,通过Redis的publish命令实现
跨服数据传输功能。
```
2026-03-04 01:30:40 +08:00

298 lines
6.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package fight
import (
"blazing/common/data"
"blazing/common/socket/errorcode"
"blazing/common/utils"
config "blazing/modules/config/model"
"blazing/modules/player/model"
"encoding/json"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/player"
"blazing/logic/service/user"
"math/rand"
"sync"
"time"
"github.com/gogf/gf/v2/util/grand"
"github.com/jinzhu/copier"
)
type FightC struct {
//准备战斗信息
ReadyInfo info.NoteReadyToFightInfo
//开始战斗信息
info.FightStartOutboundInfo
Info info.Fightinfo
IsReady bool
ownerID uint32 // 战斗发起者ID
Our *input.Input //始终等于房主ID
Opp *input.Input //对手ID
Switch map[uint32]*action.ActiveSwitchAction
Melee []config.PetBaseConfig
startl sync.Once
rand *rand.Rand
StartTime time.Time
actionChan chan action.BattleActionI // 所有操作统一从这里进入
quit chan struct{}
over chan struct{}
First *input.Input
TrueFirst *input.Input
Second *input.Input
closefight bool
overl sync.Once
waittime int
info.FightOverInfo
//战斗结束的插装
callback func(info.FightOverInfo)
}
func (f *FightC) Ownerid() uint32 {
return f.ownerID
}
func (f *FightC) GetInputByPlayer(c common.PlayerI, isOpposite bool) *input.Input {
// 判断当前玩家是否为我方玩家
isOurPlayer := c.GetInfo().UserID == f.ownerID
// 当isOurPlayer与isOpposite值不同时返回我方相同时返回对方
if isOurPlayer != isOpposite {
return f.Our
}
return f.Opp
}
func (f *FightC) GetInputByAction(c action.BattleActionI, isOpposite bool) *input.Input {
// 判断动作所属玩家是否为我方
isOurAction := c.GetPlayerID() == f.Our.Player.GetInfo().UserID
// 根据isOpposite决定是否返回相反方向的输入
if isOurAction == !isOpposite {
return f.Our
}
return f.Opp
}
// 玩家使用技能
func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity {
if f.Our.Player.GetInfo().UserID == c.GetInfo().UserID {
return f.Our.CurrentPet
} else {
return f.Opp.CurrentPet
}
}
func (f *FightC) GetOpp(c common.PlayerI) *input.Input {
return f.GetInputByPlayer(c, true)
}
// 获取随机数
func (f *FightC) GetRand() *rand.Rand {
return f.rand
}
// 获取随机数
func (f *FightC) IsFirst(play common.PlayerI) bool {
return f.TrueFirst.Player == play
}
func (f *FightC) Chat(c common.PlayerI, msg string) {
f.GetInputByPlayer(c, true).Player.SendPackCmd(50002, &user.ChatOutboundInfo{
SenderId: c.GetInfo().UserID,
SenderNickname: c.GetInfo().Nick,
Message: utils.RemoveLast(msg),
})
}
// 加载进度
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
if f.Info.Mode == info.BattleMode.PET_MELEE {
return
}
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
return
}
f.GetInputByPlayer(c, true).Player.SendPackCmd(2441, &info.LoadPercentOutboundInfo{
Id: c.GetInfo().UserID,
Percent: uint32(percent),
})
}
var meetpet = make(map[int]model.PetInfo)
func (f *FightC) initplayer(c common.PlayerI) (*input.Input, errorcode.ErrorCode) {
r := c.CanFight()
if c.CanFight() != 0 {
return nil, r
}
in := input.NewInput(f, c)
in.AllPet = make([]*info.BattlePetEntity, 0)
in.InitAttackValue()
for i := 0; i < len(c.GetInfo().PetList); i++ {
//玩家精灵重置到100等级
pet := c.GetInfo().PetList[i]
if _, ok := c.(*player.Player); ok {
pet.Level = utils.Min(pet.Level, 100)
}
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(pet, f.rand))
}
in.SortPet()
if len(in.AllPet) == 0 {
return nil, errorcode.ErrorCodes.ErrNoEligiblePokemon
}
switch f.Info.Mode {
case info.BattleMode.SINGLE_MODE:
in.AllPet = in.AllPet[:1]
case info.BattleMode.PET_MELEE:
in.AllPet = make([]*info.BattlePetEntity, 0)
var meetpet []config.PetBaseConfig
if len(f.Melee) < 6 {
return nil, errorcode.ErrorCodes.ErrSystemError
}
if c.GetInfo().UserID == f.ownerID {
meetpet = f.Melee[:3]
} else {
meetpet = f.Melee[3:]
}
for i, v := range meetpet {
if v.Lv == 0 {
v.Lv = 100
}
pet := model.GenPetInfo(int(v.MonID), 24, int(v.Nature), int(v.Effect[0]), int(v.Lv), nil, 0)
var color data.GlowFilter
err := json.Unmarshal([]byte(v.Color), &color)
if err == nil && color.Alpha != 0 {
pet.ShinyInfo = append(pet.ShinyInfo, color)
}
if len(v.Prop) == 5 {
pet.Prop = [5]uint32(v.Prop)
}
if v.Hp != 0 {
pet.MaxHp = uint32(v.Hp)
}
if len(v.SKill) != 0 {
for i := 0; i < 4; i++ {
if v.SKill[i] != 0 {
pet.SkillList[i].ID = v.SKill[i]
}
}
}
pet.CatchTime = c.GetInfo().UserID + uint32(i)*1000000
pet.Cure()
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(*pet, f.rand))
}
// for i, v := range meetpet {
// v1 := v
// if len(in.AllPet) > 2 {
// break
// }
// v1.CatchTime = c.GetInfo().UserID + uint32(i)*1000000
// v1.Cure()
// in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(v1, f.rand))
// }
//in.AllPet = in.AllPet[:3]
default:
}
in.CurrentPet = in.AllPet[0]
return in, 0
}
// RandomElfIDs 从1-2000中随机抽取n个不重复的精灵ID
func RandomElfIDs(n int) []int {
if n <= 0 || n > 2000 {
return nil
}
// 用map记录已抽取的ID避免重复
used := make(map[int]struct{}, n)
ids := make([]int, 0, n)
for len(ids) < n {
// 生成1-2000的随机数
id := grand.Intn(2000) + 1 // rand.Intn(2000)生成0-1999+1后为1-2000
// 检查是否已抽取
if _, exists := used[id]; !exists {
used[id] = struct{}{}
ids = append(ids, id)
}
}
return ids
}
func initfightready(in *input.Input) (info.FightUserInfo, []info.ReadyFightPetInfo) {
t := make([]info.ReadyFightPetInfo, len(in.AllPet))
userindo := info.FightUserInfo{
UserID: in.UserID,
Nick: in.Player.GetInfo().Nick,
}
for i := 0; i < len(in.AllPet); i++ {
err := copier.CopyWithOption(&t[i], &in.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
}
return userindo, t
}
// 被击败的ID
func (f *FightC) IsWin(c *input.Input) bool {
for _, v := range f.GetInputByPlayer(c.Player, true).AllPet {
if !v.NotAlive { //如果存活
return false
}
}
return true
}
// 广播,并是否结束回合
func (f *FightC) Broadcast(t func(ff *input.Input)) {
t(f.Our)
t(f.Opp)
}
func (f *FightC) GetOverChan() chan struct{} {
return f.over
}
func (f *FightC) GetOverInfo() info.FightOverInfo {
return f.FightOverInfo
}