Files
bl/logic/service/fight/input.go
昔念 f919047ff6 ```
fix(login): 修正用户登录时间字段命名及逻辑

将 `Onlinetime` 字段更名为 `Logintime`,以更准确反映其含义,并确保在登录时正确记录时间戳。

refactor(player): 移除冗余的 Save 方法及相关逻辑

删除 Player 结构体中的 Save、CanGetExp、CompleteLogin 和 IsNewPlayer 方法,
相关功能已迁移或不再使用。

feat(pprof): 更新 pprof 监听地址

修改 README 中的 pprof 示例命令,将监听地址从远程 IP 改为本地回环地址 `127.0.0.1
2025-11-15 13:20:42 +08:00

276 lines
6.4 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/cool"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/modules/blazing/model"
"math/rand"
"sync"
"time"
"github.com/jinzhu/copier"
)
type FightC struct {
Info info.NoteReadyToFightInfo
IsReady bool
ownerID uint32 // 战斗发起者ID
Our *input.Input //始终等于房主ID
Opp *input.Input //对手ID
Switch []*action.ActiveSwitchAction
runing bool
rand *rand.Rand
StartTime time.Time
actionChan chan action.BattleActionI // 所有操作统一从这里进入
Round int //回合数
quit chan struct{}
over chan struct{}
First *input.Input
Second *input.Input
closefight bool
overl sync.Once
waittime int
info.FightOverInfo
}
func (f *FightC) CanEscape() bool {
return f.Info.Status != info.BattleStatus.FIGHT_WITH_PLAYER
}
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.First.Player == play
}
// 加载进度
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
f.GetInputByPlayer(c, true).Player.SendLoadPercent(info.LoadPercentOutboundInfo{
Id: c.GetInfo().UserID,
Percent: uint32(percent),
})
}
func (f *FightC) initplayer(c common.PlayerI) *input.Input {
if len(c.GetInfo().PetList) == 0 {
return nil
}
in := input.NewInput(f, c)
in.AllPet = make([]*info.BattlePetEntity, 0)
in.InitAttackValue()
for i := 0; i < len(c.GetInfo().PetList); i++ {
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(&c.GetInfo().PetList[i], f.rand))
}
in.SortPet()
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)
for _, v := range RandomElfIDs(3) {
p := model.GenPetInfo(v, 24, -1, -1, -1, 100)
p.CatchTime = uint32(v)
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(p, f.rand))
}
//in.AllPet = in.AllPet[:3]
default:
}
in.CurrentPet = in.AllPet[0]
return in
}
// 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 := rand.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
}
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.PlayerI) *FightC {
f := &FightC{}
f.ownerID = p1.GetInfo().UserID
f.quit = make(chan struct{})
f.over = make(chan struct{})
f.StartTime = time.Now()
seed := f.StartTime.UnixNano() ^ int64(p1.GetInfo().UserID) ^ int64(p2.GetInfo().UserID) // ^ int64(f.Round) // 用异或运算混合多维度信息
f.rand = rand.New(rand.NewSource(seed))
f.Info = info.NoteReadyToFightInfo{
Status: status,
}
f.Info.Status = status //房主
f.Info.Mode = mode
f.Our, f.Opp = f.initplayer(p1), f.initplayer(p2)
f.Info.OurInfo, f.Info.OurPetList = initfightready(f.Our)
f.Info.OpponentInfo, f.Info.OpponentPetList = initfightready(f.Opp)
switch f.Info.Status {
case info.BattleStatus.FIGHT_WITH_PLAYER:
default:
f.Opp.Finished = true //PVE 默认boss数据直接加载完成
}
f.Our.SetOPP(f.Opp)
f.Opp.SetOPP(f.Our)
f.Broadcast(func(ff *input.Input) {
ff.Player.SendNoteReadyToFightInfo(f.Info)
})
// 60秒后判断战斗是否开始
cool.Cron.AfterFunc(60*time.Second, func() {
if !f.Our.Finished || !f.Opp.Finished { //如果有任一没有加载完成
f.Reason = info.BattleOverReason.PlayerOVerTime
switch {
case !f.Opp.Finished: //邀请方没加载完成 先判断邀请方,如果都没加载完成,就算做房主胜利
f.WinnerId = f.Our.Player.GetInfo().UserID
case !f.Our.Finished: //被邀请方没加载完成
f.WinnerId = f.Opp.Player.GetInfo().UserID
}
f.Broadcast(func(ff *input.Input) {
//todo 将血量和技能pp传回enterturn
ff.Player.SendFightEndInfo(f.FightOverInfo)
})
}
})
return f
}
// 被击败的ID
func (b *FightC) IsWin(c *input.Input, cache uint32) bool {
var tt []*info.BattlePetEntity
bbb := b.Our.AllPet
if c.Player.GetInfo().UserID == b.ownerID { //如果是房主
bbb = b.Opp.AllPet
}
for _, v := range bbb {
if v.Info.CatchTime == cache {
v.NotAlive = true
}
tt = append(tt, v)
}
for _, v := range tt {
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
}