feat(socket): 添加全局 panic 恢复机制

refactor(socket): 调整 defer recover 位置以优化错误捕获逻辑

feat(logic): 为服务器启动函数添加 defer recover
This commit is contained in:
2025-10-10 00:40:32 +08:00
parent 3639d18d60
commit d4781bf4a4
7 changed files with 89 additions and 59 deletions

View File

@@ -76,6 +76,11 @@ func (s *Server) OnOpen(conn gnet.Conn) (out []byte, action gnet.Action) {
}
func (s *Server) OnTraffic(c gnet.Conn) (action gnet.Action) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
if s.network != "tcp" {
return gnet.Close
}
@@ -166,11 +171,7 @@ func (s *Server) handleTcp(conn gnet.Conn) (action gnet.Action) {
}
func (s *Server) parser(c gnet.Conn, line []byte) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
//todo 这里待实现注入player实体
s.handler.Handle(c, line)
}

View File

@@ -61,6 +61,18 @@ func isPortAvailable(port uint64) bool {
// 如果id是0,那就是login server
func Start(serverid uint16) {
// 定义延时执行的匿名函数
defer func() {
// 使用recover()捕捉异常
if err := recover(); err != nil {
// err不为空值说明主动抛出异常
fmt.Printf("捕捉异常:%v\n", err)
} else {
// err为空值说明程序没有抛出异常
fmt.Println("程序没有异常")
}
}()
//ants.NewPool(100)
head := player.NewTomeeHandler()
head.Callback = controller.Recv

View File

@@ -32,6 +32,7 @@ type BattleActionI interface {
// SelectSkillAction 选择技能的战斗动作
type SelectSkillAction struct {
ID uint32 //技能ID
BaseAction
Skill *info.SkillEntity // 使用的技能
//PetInfo *info.BattlePetEntity // 使用技能的宠物

View File

@@ -8,6 +8,7 @@ import (
"blazing/logic/service/player"
"fmt"
"math/rand"
"reflect"
"sort"
"time"
@@ -261,14 +262,7 @@ func (f *FightC) battleLoop() {
continue
}
if a, isExpelled := paction.(*action.ActiveSwitchAction); isExpelled {
f.Broadcast(func(ff *input.Input) {
if ff.Player.GetInfo().UserID == a.PlayerID { //先给自身广播
ff.Player.SendChangePet(a.Reason)
}
})
if _, isExpelled := paction.(*action.ActiveSwitchAction); isExpelled {
if f.GetInputByAction(paction, false).CanChange {
//如果是被动切换,不计入回合结算
@@ -279,10 +273,11 @@ func (f *FightC) battleLoop() {
}
if paction.GetPlayerID() != 0 && f.Info.Status == 3 {
//AI的action实质上就是放技能如果阻止掉比如中毒那就也不能逃跑
f.GetInputByAction(paction, true).GetAction(f.Our)
if paction.GetPlayerID() != 0 {
if f.Info.Status == info.BattleStatus.FIGHT_WITH_BOSS || f.Info.Status == info.BattleStatus.FIGHT_WITH_NPC {
//AI的action实质上就是放技能如果阻止掉比如中毒那就也不能逃跑
f.GetInputByAction(paction, true).GetAction(f.Our)
}
}
@@ -334,7 +329,7 @@ func (f *FightC) battleLoop() {
case *action.ActiveSwitchAction: //切换上场的,切换方放弃出手
f.enterturn(BattleActionI[1].(*action.SelectSkillAction),
&action.SelectSkillAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
&action.SelectSkillAction{ID: 0, BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
case *action.UseItemAction: //使用道具
//fmt.Println(faction.ItemID)
@@ -378,7 +373,10 @@ func (f *FightC) battleLoop() {
// 其他情况
fmt.Println("ItemID 不在指定范围内")
}
f.enterturn(BattleActionI[1].(*action.SelectSkillAction), &action.SelectSkillAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
f.enterturn(BattleActionI[1].(*action.SelectSkillAction),
&action.SelectSkillAction{
ID: 0,
BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
default: //选择技能或者放弃出手
//回合前操作,比如挂载buff
@@ -449,10 +447,7 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
}
} else {
}
for _, e := range attacker.EffectCache {
//这里实现应该参考本地技能是否命中,然后
e.Hit(a.Skill.AttackTime != 0) //我方效果命中
@@ -488,6 +483,13 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
//然后先触发死亡效果消除所有buff
//然后触发回神效果
}
func IsNil(x interface{}) bool {
if x == nil {
return true
}
rv := reflect.ValueOf(x)
return rv.Kind() == reflect.Ptr && rv.IsNil()
}
//回合有先手方和后手方,同时有攻击方和被攻击方
@@ -519,18 +521,40 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
t.Compare_Pre(fattack, sattack) //先结算技能的优先级
return true
})
f.Second.Parseskill(f.Second, sattack) //解析到临时数据
f.Second.Exec(func(t input.Effect) bool { //回合开始前
//结算状态
t.Compare_Pre(fattack, sattack) //先结算技能的优先级
return true
})
switch {
case sattack.ID != 0:
switch {
case fattack.ID != 0: //房主也放弃出手
switch {
case fattack.Skill.Priority < sattack.Skill.Priority:
case fattack.Skill.Priority < sattack.Skill.Priority:
fattack, sattack = sattack, fattack //互换先手权
case fattack.Skill.Priority == sattack.Skill.Priority:
fattack, sattack = sattack, fattack //互换先手权
f.First, f.Second = f.Second, f.First
case fattack.Skill.Priority == sattack.Skill.Priority:
if f.Second.GetProp(4, false) > f.First.GetProp(4, false) {
if f.Second.GetProp(4, false) > f.First.GetProp(4, false) {
fattack, sattack = sattack, fattack //互换先手权
f.First, f.Second = f.Second, f.First
}
}
default: //房主放弃出手
fattack, sattack = sattack, fattack //互换先手权
f.First, f.Second = f.Second, f.First
}
}
var attacker, defender *input.Input
//开始回合操作
for i := 0; i < 2; i++ {
@@ -553,10 +577,16 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
canuseskill := true
// 实际上攻击方 还有系统选择放弃出手的
if fattack.Skill == nil || attacker.CurrentPet.Info.Hp <= 0 || !fattack.Skill.CanUse() {
attacker.AttackValue.SkillID = 0
if IsNil(oldskill) || attacker.CurrentPet.Info.Hp <= 0 {
// attacker.AttackValue.SkillID = 0
canuseskill = false
} else {
if !oldskill.(*info.SkillEntity).CanUse() {
// attacker.AttackValue.SkillID = 0
canuseskill = false
}
}
canuseskillok := attacker.Exec(func(t input.Effect) bool { //这个是能否使用技能
@@ -572,15 +602,15 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
if i == 0 { //
f.processSkillAttack(attacker, defender, fattack)
fattack.Skill = oldskill.(*info.SkillEntity) //还原技能效果
fattack.Skill.Info.PP-- //减少PP
} else {
f.processSkillAttack(attacker, defender, sattack)
sattack.Skill = oldskill.(*info.SkillEntity) //还原技能效果
sattack.Skill.Info.PP-- //减少PP
}
}
fattack.Skill.Info.PP-- //减少PP
//技能使用后
defender.Exec(func(t input.Effect) bool {
t.Skill_Use(input.Ctx{Input: attacker})
@@ -589,12 +619,14 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
})
fmt.Println(i,
// "玩家技能:", oldskill.(*info.SkillEntity).ID,
"玩家技能伤害:", attacker.DamageZone.Damage,
"自身剩余血量:", attacker.CurrentPet.Info.Hp,
"对手剩余血量:", defender.CurrentPet.Info.Hp,
)
if defender.CurrentPet.Info.Hp == 0 {
defender.AttackValue.SkillID = 0
// defender.AttackValue.SkillID = 0
defender.CanChange = true //被打死就可以切精灵了
if f.IsWin(attacker, defender.CurrentPet.Info.CatchTime) { //然后检查是否战斗结束
var WinnerId uint32

View File

@@ -6,11 +6,9 @@ import (
"blazing/modules/blazing/model"
"math/rand"
"context"
"fmt"
"strconv"
"github.com/gogf/gf/v2/os/glog"
"github.com/shopspring/decimal"
"github.com/tnnmigga/enum"
)
@@ -61,12 +59,6 @@ type SkillEntity struct {
// CreateSkill 创建战斗技能实例可指定是否无限PP
func CreateSkill(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity) *SkillEntity {
//如果PP是-1 ,那就是无限PP
// ID小于10001的视为无效技能
// if skill.ID < 10001 {
// return nil
// }
var ret SkillEntity
ret.Rand = rand
@@ -74,22 +66,11 @@ func CreateSkill(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity)
// 从资源仓库获取技能数据
move, ok := xmlres.SkillMap[int(skill.ID)]
if !ok {
glog.Error(context.Background(), "技能ID无效", "id", skill.ID)
} else {
if ok {
ret.Move = move
}
// // 解析副作用参数
// sideEffectArgs := parseSideEffectArgs(move.SideEffectArg)
// tt := strings.Split(move.SideEffect, " ")
// rf, err := strSliceToIntSlice(tt)
// if err == nil {
// ret.SideEffects = rf
// }
ret.Info = skill
// ret.SideEffectArgs = sideEffectArgs
return &ret
}

View File

@@ -51,6 +51,7 @@ func (f *FightC) ChangePet(c common.PlayerI, id uint32) {
BaseAction: action.NewBaseAction(c.GetInfo().UserID),
}
f.Switch = append(f.Switch, ret)
f.GetInputByPlayer(c, false).Exec(func(t input.Effect) bool {
t.OnOwnerSwitchOut(input.Ctx{})
@@ -64,6 +65,12 @@ func (f *FightC) ChangePet(c common.PlayerI, id uint32) {
return true
})
f.GetInputByPlayer(c, false).CurrentPet, ret.Reason = f.GetInputByPlayer(c, false).GetPet(id)
f.Broadcast(func(ff *input.Input) { //先给自身广播
if ff.Player.GetInfo().UserID == c.GetInfo().UserID {
ff.Player.SendChangePet(ret.Reason)
}
})
f.GetInputByPlayer(c, false).Exec(func(t input.Effect) bool {
t.OnOwnerSwitchIn(input.Ctx{})
@@ -86,7 +93,7 @@ func (f *FightC) UseSkill(c common.PlayerI, id int32) {
BaseAction: action.NewBaseAction(c.GetInfo().UserID),
}
//ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet
ret.ID = uint32(id)
for _, v := range f.GetInputByPlayer(c, false).CurrentPet.Skills {
if v != nil && v.ID == int(id) {
@@ -120,18 +127,14 @@ func (f *FightC) ReadyFight(c common.PlayerI) {
}
switch f.Info.Status {
case 1: // 1v1
case 1: //pvp
f.GetInputByPlayer(c, false).Finished = true
if f.GetInputByPlayer(c, true).Finished {
rrsult()
}
case 2: // 6v6
f.GetInputByPlayer(c, false).Finished = true
if f.GetInputByPlayer(c, true).Finished {
rrsult()
}
rrsult()
case 3: // 野怪战斗
//判断捕捉率大于0

View File

@@ -31,7 +31,7 @@ func KickPlayer(userid uint32) { //踢出玩家
//var player *entity.Player
if player1, ok := Mainplayer.Load(userid); ok {
//取成功,否则创建
player1.Save() //先保存数据再返回
//player1.Save() //先保存数据再返回
head := NewTomeeHeader(1001, userid)
head.Result = uint32(errorcode.ErrorCodes.ErrAccountLoggedInElsewhere)
//实际上这里有个问题,会造成重复保存问题