From 3b6e69f1f4990955a5c67b9db2508810a25503d6 Mon Sep 17 00:00:00 2001 From: 1 <1@72wo.cn> Date: Mon, 25 Aug 2025 16:44:50 +0000 Subject: [PATCH 1/4] =?UTF-8?q?refactor(fight):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=9A=8F=E6=9C=BA=E6=95=B0=E7=94=9F=E6=88=90=E5=99=A8=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=B9=B6=E4=BC=98=E5=8C=96=E6=88=98=E6=96=97=E6=8A=80?= =?UTF-8?q?=E8=83=BDPP=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../battle => common/utils}/random/random.go | 0 logic/service/fight/battle/node/def.go | 140 ----------- logic/service/fight/battle/node/node.go | 40 --- logic/service/fight/battle/node/t.go | 233 ------------------ logic/service/fight/battle/over/pool.go | 87 ------- logic/service/fight/battle/over/reason.go | 60 ----- .../battle/skill/effect/EffectContainer.go | 148 ----------- .../battle/skill/effect/base/BurnEffect.go | 32 --- .../fight/battle/skill/effect/manger.go | 76 ------ logic/service/fight/info/BattleSkillEntity.go | 38 +-- logic/service/fight/info/battle.go | 38 ++- .../fight/{battle/start => }/start_test.go | 2 +- 12 files changed, 40 insertions(+), 854 deletions(-) rename {logic/service/fight/battle => common/utils}/random/random.go (100%) delete mode 100644 logic/service/fight/battle/node/def.go delete mode 100644 logic/service/fight/battle/node/node.go delete mode 100644 logic/service/fight/battle/node/t.go delete mode 100644 logic/service/fight/battle/over/pool.go delete mode 100644 logic/service/fight/battle/over/reason.go delete mode 100644 logic/service/fight/battle/skill/effect/EffectContainer.go delete mode 100644 logic/service/fight/battle/skill/effect/base/BurnEffect.go delete mode 100644 logic/service/fight/battle/skill/effect/manger.go rename logic/service/fight/{battle/start => }/start_test.go (98%) diff --git a/logic/service/fight/battle/random/random.go b/common/utils/random/random.go similarity index 100% rename from logic/service/fight/battle/random/random.go rename to common/utils/random/random.go diff --git a/logic/service/fight/battle/node/def.go b/logic/service/fight/battle/node/def.go deleted file mode 100644 index 2ba965c72..000000000 --- a/logic/service/fight/battle/node/def.go +++ /dev/null @@ -1,140 +0,0 @@ -package node - -import "fmt" - -// 基础上下文 -type EffectContext struct { - Turn int // 当前回合数 - Actor string // 当前行动者(谁在出手) - Target string // 当前目标(技能攻击对象) - Skill string // 使用的技能 - Extra map[string]interface{} // 临时附加信息(状态、标记、计算中间值等) -} - -// 节点类型 -type NodeFunc func(ctx *EffectContext, next func()) - -type EffectNode struct { - Name string - Exec NodeFunc -} - -// 节点管理器 -type NodeRunner struct { - nodes []*EffectNode - index int - ctx *EffectContext -} - -func NewNodeRunner(ctx *EffectContext, nodes []*EffectNode) *NodeRunner { - return &NodeRunner{ - nodes: nodes, - index: 0, - ctx: ctx, - } -} - -// 执行下一个节点 -func (r *NodeRunner) Run() { - if r.index >= len(r.nodes) { - return - } - current := r.nodes[r.index] - r.index++ - current.Exec(r.ctx, r.Run) -} - -// 跳过当前节点 -func (r *NodeRunner) Skip() { - r.index++ - r.Run() -} - -// ------------------------ -// 定义战斗流程节点 -// ------------------------ -func BuildBattleNodes() []*EffectNode { - return []*EffectNode{ - {Name: "战斗开始", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("OnBattleStart") - next() - }}, - {Name: "登场/切换", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("OnSwitchIn / OnSwitchOut / OnTransform") - next() - }}, - {Name: "回合开始", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("TurnStart") - next() - }}, - {Name: "操作阶段", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("选择技能 / 使用道具 / 切换") - next() - }}, - {Name: "先手判定", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("先手权判定") - next() - }}, - {Name: "先手出手-前置", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("BeforeUseSkillCheck / BeforeHit / OnMiss") - next() - }}, - {Name: "先手出手-技能命中", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("技能命中判定 / 初始伤害公式 / 红伤数值计算") - next() - }}, - {Name: "先手出手-技能效果结算", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("技能效果结算 / 魂印 / 套装 / 回合类效果") - next() - }}, - {Name: "先手出手-伤害结算", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("最终伤害生效 / 体力扣除") - next() - }}, - {Name: "先手出手-行动结束", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("行动后效果 / 额外行动 / 机盖弹伤 / 出手结束效果") - next() - }}, - {Name: "后手出手", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("后手节点同先手节点") - next() - }}, - {Name: "回合结束后①", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("回合结束后通用时点① / 桃园回血 / 回合扣减①") - next() - }}, - {Name: "回合结束后②", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("回合结束后通用时点② / 战争猎魔 / 16年魂印续航") - next() - }}, - {Name: "死亡判定", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("死亡结算 / 保护机制") - next() - }}, - {Name: "击败/未击败判定", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("击败触发效果 / 未击败触发效果") - next() - }}, - {Name: "进入下回合", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("进入下回合,流程重新开始") - next() - }}, - } -} - -// ------------------------ -// 测试运行 -// ------------------------ -func TestBattleFlow() { - ctx := &EffectContext{ - Turn: 1, - Actor: "PlayerA", - Target: "PlayerB", - Skill: "火球", - Extra: map[string]interface{}{}, - } - - nodes := BuildBattleNodes() - runner := NewNodeRunner(ctx, nodes) - runner.Run() -} diff --git a/logic/service/fight/battle/node/node.go b/logic/service/fight/battle/node/node.go deleted file mode 100644 index 6d81a69cf..000000000 --- a/logic/service/fight/battle/node/node.go +++ /dev/null @@ -1,40 +0,0 @@ -package node - -import "github.com/tnnmigga/enum" - -// ================= BaseEvent ================= -// EnumBaseEvent 定义了战斗中可能触发的基础事件类型。 -// 这些事件通常作为 Effect 的触发点,例如攻击前、受到伤害后等。 -type EnumBaseEvent string - -var BaseEvent = enum.New[struct { - Attack EnumBaseEvent `enum:"attack"` // 攻击事件 - Damage EnumBaseEvent `enum:"damage"` // 伤害事件 - Heal EnumBaseEvent `enum:"heal"` // 治疗事件 - Buff EnumBaseEvent `enum:"buff"` // Buff/状态效果事件 - Turn EnumBaseEvent `enum:"turn"` // 回合开始或结束事件 - Death EnumBaseEvent `enum:"death"` // 死亡事件 - Skill EnumBaseEvent `enum:"skill"` // 技能释放事件 -}]() - -// ================= HookPhase ================= -// EnumHookPhase 定义了事件触发的阶段。 -// 在同一个事件中,某些效果可能需要在事件发生前(Before)触发, -// 也可能需要在事件发生后(After)触发。 -type EnumHookPhase string - -var HookPhase = enum.New[struct { - Before EnumHookPhase `enum:"before"` // 事件发生前触发 - After EnumHookPhase `enum:"after"` // 事件发生后触发 -}]() - -// ================= LifeType ================= -// EnumLifeType 定义了效果(Effect)的生命周期。 -// 用来决定效果是持续多个回合、按次数消耗,还是永久存在。 -type EnumLifeType string - -var LifeType = enum.New[struct { - TurnBased EnumLifeType `enum:"turn_based"` // 按回合数存续(如中毒3回合) - CountBased EnumLifeType `enum:"count_based"` // 按次数存续(如可抵挡2次攻击) - Permanent EnumLifeType `enum:"permanent"` // 永久存在(如种族特性/被动) -}]() diff --git a/logic/service/fight/battle/node/t.go b/logic/service/fight/battle/node/t.go deleted file mode 100644 index 2972609da..000000000 --- a/logic/service/fight/battle/node/t.go +++ /dev/null @@ -1,233 +0,0 @@ -package battle - -import "fmt" - -// ==================== 基础类型 ==================== -type BaseEvent string -type HookPhase string -type LifeType string - -const ( - Before HookPhase = "before" - After HookPhase = "after" - - TurnBased LifeType = "turn_based" - CountBased LifeType = "count_based" - Permanent LifeType = "permanent" -) - -type EffectContext struct { - Actor string - Target string - Skill string - Extra map[string]interface{} - Success bool -} - -type Effect struct { - Name string - Trigger string - LifeType LifeType - Duration int - Phase HookPhase - Handler func(ctx *EffectContext) bool -} - -type EffectNode struct { - Name string - Exec func(ctx *EffectContext, next func()) -} - -type EffectManager struct { - nodes []*EffectNode - effects map[string][]*Effect -} - -func NewEffectManager(nodes []*EffectNode) *EffectManager { - return &EffectManager{ - nodes: nodes, - effects: make(map[string][]*Effect), - } -} - -func (m *EffectManager) RegisterEffect(node string, eff *Effect) { - m.effects[node] = append(m.effects[node], eff) -} - -func (m *EffectManager) ExecuteNode(nodeName string, ctx *EffectContext) { - if effs, ok := m.effects[nodeName]; ok { - for _, eff := range effs { - if eff.Handler != nil { - eff.Handler(ctx) - } - } - } -} - -func (m *EffectManager) RunBattle(ctx *EffectContext) { - var i int - var execNext func() - execNext = func() { - if i >= len(m.nodes) { - return - } - node := m.nodes[i] - i++ - node.Exec(ctx, execNext) - } - execNext() -} - -// ==================== 节点定义 ==================== -func BuildBattleNodes() []*EffectNode { - return []*EffectNode{ - {Name: "战斗开始", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("OnBattleStart") - next() - }}, - {Name: "登场/切换", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("OnSwitchIn / OnSwitchOut / OnTransform") - next() - }}, - {Name: "回合开始", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("TurnStart") - next() - }}, - {Name: "操作阶段", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("选择技能 / 使用道具 / 切换") - next() - }}, - {Name: "先手判定", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("先手权判定") - next() - }}, - {Name: "先手出手-前置", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("BeforeUseSkillCheck / BeforeHit / OnMiss") - next() - }}, - {Name: "先手出手-技能命中", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("技能命中判定 / 初始伤害公式 / 红伤数值计算") - next() - }}, - {Name: "先手出手-技能效果结算", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("技能效果结算 / 魂印 / 套装 / 回合类效果") - next() - }}, - {Name: "先手出手-伤害结算", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("最终伤害生效 / 体力扣除") - next() - }}, - {Name: "先手出手-行动结束", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("行动后效果 / 额外行动 / 机盖弹伤 / 出手结束效果") - next() - }}, - {Name: "后手出手", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("后手节点同先手节点") - next() - }}, - {Name: "回合结束后①", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("回合结束后通用时点① / 桃园回血 / 回合扣减①") - next() - }}, - {Name: "回合结束后②", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("回合结束后通用时点② / 战争猎魔 / 16年魂印续航") - next() - }}, - {Name: "死亡判定", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("死亡结算 / 保护机制") - next() - }}, - {Name: "击败/未击败判定", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("击败触发效果 / 未击败触发效果") - next() - }}, - {Name: "进入下回合", Exec: func(ctx *EffectContext, next func()) { - fmt.Println("进入下回合,流程重新开始") - next() - }}, - } -} - -// ==================== 注册45个原始效果 ==================== -func RegisterOriginalEffects(manager *EffectManager) { - // 战斗开始类 - manager.RegisterEffect("战斗开始", &Effect{ - Name: "天生特性", - LifeType: Permanent, - Phase: Before, - Handler: func(ctx *EffectContext) bool { - fmt.Println(ctx.Actor, "天生特性触发") - return true - }, - }) - manager.RegisterEffect("战斗开始", &Effect{ - Name: "战斗开始印记", - LifeType: Permanent, - Phase: Before, - Handler: func(ctx *EffectContext) bool { - fmt.Println(ctx.Actor, "战斗开始印记触发") - return true - }, - }) - - // 登场/切换类 - manager.RegisterEffect("登场/切换", &Effect{ - Name: "登场魂印", - LifeType: CountBased, - Duration: 2, - Phase: Before, - Handler: func(ctx *EffectContext) bool { - fmt.Println(ctx.Actor, "登场魂印触发") - return true - }, - }) - - // 回合开始 - manager.RegisterEffect("回合开始", &Effect{ - Name: "回合开始Buff", - LifeType: TurnBased, - Duration: 3, - Phase: Before, - Handler: func(ctx *EffectContext) bool { - fmt.Println(ctx.Actor, "回合开始Buff生效") - return true - }, - }) - - // 先手出手节点示例 - manager.RegisterEffect("先手出手-前置", &Effect{ - Name: "先手准备效果", - LifeType: CountBased, - Duration: 1, - Phase: Before, - Handler: func(ctx *EffectContext) bool { - fmt.Println(ctx.Actor, "先手前置效果触发") - return true - }, - }) - manager.RegisterEffect("先手出手-技能效果结算", &Effect{ - Name: "技能附加效果", - LifeType: CountBased, - Duration: 2, - Phase: After, - Handler: func(ctx *EffectContext) bool { - fmt.Println(ctx.Actor, "技能附加效果生效") - return true - }, - }) - - // 回合结束后① - manager.RegisterEffect("回合结束后①", &Effect{ - Name: "回合结束Buff", - LifeType: TurnBased, - Duration: 3, - Phase: After, - Handler: func(ctx *EffectContext) bool { - fmt.Println(ctx.Actor, "回合结束后Buff触发") - return true - }, - }) - - // 你可以继续按此格式,将原45个效果依次映射到16节点 - // 节点选择 Before/After,LifeType选择 TurnBased/CountBased/Permanent -} diff --git a/logic/service/fight/battle/over/pool.go b/logic/service/fight/battle/over/pool.go deleted file mode 100644 index 32b859b45..000000000 --- a/logic/service/fight/battle/over/pool.go +++ /dev/null @@ -1,87 +0,0 @@ -package over - -import "sync" - -// 战斗结束原因池,用于管理战斗结束的各种原因数据 -type BattleOverPool struct { - dataMap map[EnumBattleOverReason]BattleOverData - size int - value BattleOverData - mutex sync.RWMutex // 用于并发安全 -} - -// 初始化战斗结束原因池 -func NewBattleOverPool() *BattleOverPool { - return &BattleOverPool{ - dataMap: make(map[EnumBattleOverReason]BattleOverData), - } -} - -// 添加战斗结束原因 -func (p *BattleOverPool) PushReason(reason EnumBattleOverReason, data BattleOverData) { - p.mutex.Lock() - defer p.mutex.Unlock() - - p.dataMap[reason] = data - p.value = data - p.size++ -} - -// 获取并移除指定的战斗结束原因 -func (p *BattleOverPool) PopReason(reason EnumBattleOverReason) BattleOverData { - p.mutex.Lock() - defer p.mutex.Unlock() - - data, exists := p.dataMap[reason] - if exists { - delete(p.dataMap, reason) - p.size-- - } - return data -} - -// 获取并移除所有战斗结束原因 -func (p *BattleOverPool) PopReasons() []BattleOverData { - p.mutex.Lock() - defer p.mutex.Unlock() - - reasons := make([]BattleOverData, 0, p.size) - for _, data := range p.dataMap { - reasons = append(reasons, data) - } - p.dataMap = make(map[EnumBattleOverReason]BattleOverData) - p.size = 0 - p.value = nil - return reasons -} - -// 获取最后添加的战斗结束原因 -func (p *BattleOverPool) PopReasonLast() BattleOverData { - p.mutex.Lock() - defer p.mutex.Unlock() - - data := p.value - p.value = nil - if p.size > 0 { - p.size-- - } - // 清空map - if p.size == 0 { - p.dataMap = make(map[EnumBattleOverReason]BattleOverData) - } - return data -} - -// 判断战斗是否应该结束 -func (p *BattleOverPool) IsShouldOver() bool { - p.mutex.RLock() - defer p.mutex.RUnlock() - return p.size > 0 -} - -// 获取当前战斗结束原因的数量 -func (p *BattleOverPool) Size() int { - p.mutex.RLock() - defer p.mutex.RUnlock() - return p.size -} diff --git a/logic/service/fight/battle/over/reason.go b/logic/service/fight/battle/over/reason.go deleted file mode 100644 index e5273aa08..000000000 --- a/logic/service/fight/battle/over/reason.go +++ /dev/null @@ -1,60 +0,0 @@ -package over - -import ( - "github.com/tnnmigga/enum" -) - -// 战斗结束原因数据接口 -type BattleOverData interface{} - -// 玩家离线数据 -type PlayerOfflineData struct { - // 可以根据需要添加字段 - PlayerID int64 -} - -// 玩家逃脱数据 -type PlayerEscapeData struct { - // 可以根据需要添加字段 - PlayerID int64 -} - -// 玩家捕获成功数据 -type PlayerCaptureSuccessData struct { - // 可以根据需要添加字段 - CaptorID int64 - TargetID int64 - CaptureTime int64 -} - -// 默认结束数据 -type DefaultEndData struct { - // 可以根据需要添加字段 - Reason string -} - -// 战斗结束原因枚举 -type EnumBattleOverReason int - -var BattleOverReason = enum.New[struct { - PlayerOffline EnumBattleOverReason `enum:"1"` //掉线 - PlayerEscape EnumBattleOverReason `enum:"2"` //逃跑 - PlayerCaptureSuccess EnumBattleOverReason `enum:"3"` //捕捉成功 - DefaultEnd EnumBattleOverReason `enum:"4"` //默认结束 -}]() - -// 获取对应的类型 -func (e EnumBattleOverReason) DataType() interface{} { - switch e { - case BattleOverReason.PlayerOffline: - return PlayerOfflineData{} - case BattleOverReason.PlayerEscape: - return PlayerEscapeData{} - case BattleOverReason.PlayerCaptureSuccess: - return PlayerCaptureSuccessData{} - case BattleOverReason.DefaultEnd: - return DefaultEndData{} - default: - return nil - } -} diff --git a/logic/service/fight/battle/skill/effect/EffectContainer.go b/logic/service/fight/battle/skill/effect/EffectContainer.go deleted file mode 100644 index cd228d7d8..000000000 --- a/logic/service/fight/battle/skill/effect/EffectContainer.go +++ /dev/null @@ -1,148 +0,0 @@ -package effect - -import ( - "blazing/logic/service/fight/battle/node" - "sort" - - "github.com/tnnmigga/enum" -) - -// ======================== -// 上下文:一次效果执行环境 -// ======================== -type EffectContext struct { - Parent string // 上下文来源(比如 "Skill"、"Buff"、"Passive") - Trigger node.EnumEffectTrigger // 当前触发的节点 - Container *EffectContainer // 效果容器(通常挂在 Actor 身上) - Effect *Effect // 当前正在执行的 Effect - Available bool // 是否可用 - Success bool // 是否执行成功 - Done bool // 是否中止后续执行 -} - -// ======================== -// Effect: 单个效果 -// ======================== -type Effect struct { - ID uint32 // 唯一标识 - Trigger node.EnumEffectTrigger // 触发节点 - Priority int // 执行优先级,数值越大越先执行 - LifeType EnumLifeType //回合效果 是否可持续 继承到下一直精灵 - Duration int // 持续回合/次(0 = 即时生效,>0 = 回合数 ,负数是永久) - Stacks int // 当前层数 - MaxStack int // 最大叠加层数 - Handler func(ctx *EffectContext, next func()) bool // 执行逻辑,返回 true 表示继续保留 //TODO 内部判断是否切换了精灵,是否满足条件 - -} - -// ================= LifeType ================= -type EnumLifeType int - -var LifeType = enum.New[struct { - TurnBased EnumLifeType `enum:"1"` // 回合数限制 - CountBased EnumLifeType `enum:"2"` // 次数限制 -}]() - -// ======================== -// 容器:存放多个效果 -// ======================== -type EffectContainer struct { - //GlobalEffects []*Effect // 全局常驻/回合/次数效果 - Effects []*Effect //effects 实际上全局就是effect无限回合 -} - -// 添加效果 -func (c *EffectContainer) AddEffect(e *Effect) { - // 如果已有同 ID 的效果,尝试叠加 - for _, eff := range c.Effects { - if eff.ID == e.ID { - if eff.Stacks < eff.MaxStack { - eff.Stacks++ - } - return - } - } - // 否则新加入 - c.Effects = append(c.Effects, e) -} - -// 添加全局效果 -func (c *EffectContainer) AddGlobalEffects(e *Effect) { - // 如果已有同 ID 的效果,尝试叠加 - for _, eff := range c.GlobalEffects { - if eff.ID == e.ID { - if eff.Stacks < eff.MaxStack { - eff.Stacks++ - } - return - } - } - // 否则新加入 - c.GlobalEffects = append(c.GlobalEffects, e) -} - -// 触发执行 -func (c *EffectContainer) Trigger(trigger node.EnumEffectTrigger, ctx *EffectContext) { - var candidates []*Effect - for _, eff := range c.Effects { - if eff.Trigger == trigger { - candidates = append(candidates, eff) - } - } - - // 按优先级排序 - sort.SliceStable(candidates, func(i, j int) bool { - return candidates[i].Priority > candidates[j].Priority - }) - - // 执行 - for _, eff := range candidates { - ctx.Effect = eff - keep := eff.Apply(ctx) - - if !keep { - // 持续回合结束 / 返回 false 的 effect 删除 - c.removeEffect(eff) - } - - if ctx.Done { - break // 被拦截 - } - } -} - -// 每回合结束时调用,用于处理持续时间 -func (c *EffectContainer) Tick() { - var remain []*Effect - for _, eff := range c.Effects { - if eff.Duration > 0 { - eff.Duration-- - } - if eff.Duration != 0 { // 保留 (负数表示永久) - remain = append(remain, eff) - } - } - c.Effects = remain -} - -// 删除 -func (c *EffectContainer) removeEffect(e *Effect) { - var remain []*Effect - for _, eff := range c.Effects { - if eff != e { - remain = append(remain, eff) - } - } - c.Effects = remain -} - -// 清理过期效果 -func (c *EffectContainer) Cleanup() { - var alive []*Effect - for _, e := range c.Effects { - if e.Duration != 0 { - alive = append(alive, e) - } - } - c.Effects = alive //挂载到普通effect -} diff --git a/logic/service/fight/battle/skill/effect/base/BurnEffect.go b/logic/service/fight/battle/skill/effect/base/BurnEffect.go deleted file mode 100644 index 2e5fcd300..000000000 --- a/logic/service/fight/battle/skill/effect/base/BurnEffect.go +++ /dev/null @@ -1,32 +0,0 @@ -package base - -import ( - "blazing/logic/service/fight/battle/node" - "fmt" -) - -type BurnEffect struct { - life LifeCycle -} - -func NewBurnEffect(turns int) *BurnEffect { - return &BurnEffect{life: NewTurnLife(turns)} -} - -func (b *BurnEffect) Trigger() node.EnumEffectTrigger { - return node.EffectTrigger.TurnEnd // 每回合结束触发掉血 -} - -func (b *BurnEffect) Apply(ctx *node.EffectContext, next func()) { - fmt.Printf("[%s] 在回合结束时受灼烧伤害!\n", ctx.Target) - b.life.Use() // 消耗一次触发次数(如果你定义为按次数存活) - next() -} - -func (b *BurnEffect) Tick() { - b.life.Tick() -} - -func (b *BurnEffect) Alive() bool { - return b.life.Alive() -} diff --git a/logic/service/fight/battle/skill/effect/manger.go b/logic/service/fight/battle/skill/effect/manger.go deleted file mode 100644 index 5ba2827ed..000000000 --- a/logic/service/fight/battle/skill/effect/manger.go +++ /dev/null @@ -1,76 +0,0 @@ -package effect - -import ( - "blazing/logic/service/fight/battle/node" - - "github.com/tnnmigga/enum" -) - -type EffectManager struct { - containers map[string]*EffectContainer -} - -func NewEffectManager() *EffectManager { - return &EffectManager{ - containers: make(map[string]*EffectContainer), - } -} - -// 添加效果 -func (m *EffectManager) AddEffect(owner string, e *Effect) { - if _, ok := m.containers[owner]; !ok { - m.containers[owner] = &EffectContainer{} - } - m.containers[owner].AddEffect(e) -} - -// 触发事件,按顺序链式执行效果 -func (m *EffectManager) Trigger(owner string, trigger node.EnumEffectTrigger, ctx *EffectContext) { - container, ok := m.containers[owner] - if !ok { - return - } - - var idx int - var next func() - next = func() { - if idx >= len(container.Effects) { - return - } - e := container.Effects[idx] - idx++ - // 判断触发器匹配 - if e.Trigger == trigger { - e.Handler(ctx, next) - if e.LifeType == e.LifeType { - e.Duration-- - } - } else { - // 不匹配直接跳过 - next() - } - } - - next() - container.Cleanup() -} - -type EnumBaseEvent string - -var BaseEvent = enum.New[struct { - Attack EnumBaseEvent `enum:"attack"` - Damage EnumBaseEvent `enum:"damage"` - Heal EnumBaseEvent `enum:"heal"` - Buff EnumBaseEvent `enum:"buff"` - Turn EnumBaseEvent `enum:"turn"` - Death EnumBaseEvent `enum:"death"` - Skill EnumBaseEvent `enum:"skill"` -}]() - -// ================= HookPhase ================= -type EnumHookPhase string - -var HookPhase = enum.New[struct { - Before EnumHookPhase `enum:"before"` - After EnumHookPhase `enum:"after"` -}]() diff --git a/logic/service/fight/info/BattleSkillEntity.go b/logic/service/fight/info/BattleSkillEntity.go index 173fac59d..637c808de 100644 --- a/logic/service/fight/info/BattleSkillEntity.go +++ b/logic/service/fight/info/BattleSkillEntity.go @@ -3,7 +3,8 @@ package info import ( element "blazing/common/data/Element" "blazing/common/data/xml/skill" - "blazing/logic/service/fight/battle/random" + "blazing/common/utils/random" + "context" "fmt" "strconv" @@ -103,41 +104,6 @@ func (s *BattleSkillEntity) Type() element.ElementType { return element.ElementType(s.Move.Type) } -// UseOnce 使用一次技能(消耗1点PP) -func (s *BattleSkillEntity) UseOnce() *BattleSkillEntity { - if !s.InfinityPP { - s.PP-- - s.correctPP() - } - return s -} - -// AddPP 增加PP值 -func (s *BattleSkillEntity) AddPP(value int) *BattleSkillEntity { - if !s.InfinityPP { - s.PP += value - s.correctPP() - } - return s -} - -// MinusPP 减少PP值 -func (s *BattleSkillEntity) MinusPP(value int) *BattleSkillEntity { - if !s.InfinityPP { - s.PP -= value - s.correctPP() - } - return s -} - -// 修正PP值,确保在0到MaxPP之间 -func (s *BattleSkillEntity) correctPP() { - if s.PP < 0 { - s.PP = 0 - } else if s.PP > s.MaxPP { - s.PP = s.MaxPP - } -} func (u *BattleSkillEntity) NewBattleAction(ctx context.Context) { ret := BattleAction{} diff --git a/logic/service/fight/info/battle.go b/logic/service/fight/info/battle.go index 1d758897d..fdb995c11 100644 --- a/logic/service/fight/info/battle.go +++ b/logic/service/fight/info/battle.go @@ -1,7 +1,7 @@ package info import ( - "blazing/logic/service/fight/battle/random" + "blazing/common/utils/random" "github.com/tnnmigga/enum" ) @@ -21,3 +21,39 @@ var BattleMode = enum.New[struct { PVE EnumBattleMode `enum:"3"` PVP EnumBattleMode `enum:"1"` }]() + +// 玩家离线数据 +type PlayerOfflineData struct { + // 可以根据需要添加字段 + PlayerID int64 +} + +// 玩家逃脱数据 +type PlayerEscapeData struct { + // 可以根据需要添加字段 + PlayerID int64 +} + +// 玩家捕获成功数据 +type PlayerCaptureSuccessData struct { + // 可以根据需要添加字段 + CaptorID int64 + TargetID int64 + CaptureTime int64 +} + +// 默认结束数据 +type DefaultEndData struct { + // 可以根据需要添加字段 + Reason string +} + +// 战斗结束原因枚举 +type EnumBattleOverReason int + +var BattleOverReason = enum.New[struct { + PlayerOffline EnumBattleOverReason `enum:"1"` //掉线 + PlayerEscape EnumBattleOverReason `enum:"2"` //逃跑 + PlayerCaptureSuccess EnumBattleOverReason `enum:"3"` //捕捉成功 + DefaultEnd EnumBattleOverReason `enum:"4"` //默认结束 +}]() diff --git a/logic/service/fight/battle/start/start_test.go b/logic/service/fight/start_test.go similarity index 98% rename from logic/service/fight/battle/start/start_test.go rename to logic/service/fight/start_test.go index f983d660a..fb03b747f 100644 --- a/logic/service/fight/battle/start/start_test.go +++ b/logic/service/fight/start_test.go @@ -1,4 +1,4 @@ -package start +package fight import ( "fmt" From 32d0b7d80462364d00e2c33fe9cf41cb0bf6ac49 Mon Sep 17 00:00:00 2001 From: 1 <1@72wo.cn> Date: Mon, 25 Aug 2025 16:49:38 +0000 Subject: [PATCH 2/4] =?UTF-8?q?refactor(fight):=20=E6=B8=85=E7=90=86?= =?UTF-8?q?=E6=97=A0=E7=94=A8=E4=BB=A3=E7=A0=81=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fight/battle/skill/effect/impl/effect1.go | 21 ------------------- logic/service/fight/info/BattleAction.go | 1 - .../fight/info/BattleInputSourceEntity.go | 2 +- logic/service/fight/info/battle_1v1.go | 4 ++-- 4 files changed, 3 insertions(+), 25 deletions(-) delete mode 100644 logic/service/fight/battle/skill/effect/impl/effect1.go diff --git a/logic/service/fight/battle/skill/effect/impl/effect1.go b/logic/service/fight/battle/skill/effect/impl/effect1.go deleted file mode 100644 index a1d7a70dc..000000000 --- a/logic/service/fight/battle/skill/effect/impl/effect1.go +++ /dev/null @@ -1,21 +0,0 @@ -package impl - -import ( - "blazing/logic/service/fight/battle/node" - "blazing/logic/service/fight/battle/skill/effect" - "fmt" -) - -var burn = &effect.Effect{ - Name: "Burn", - Trigger: node.EnumEffectTrigger{ - Event: BaseEvent.Damage, // ✅ 类型安全 - Phase: HookPhase.After, - }, - LifeType: LifeType.TurnBased, - Duration: 3, - Handler: func(ctx *EffectContext, next func()) { - fmt.Printf("[%s] 灼烧 %s\n", ctx.Actor, ctx.Target) - next() - }, -} diff --git a/logic/service/fight/info/BattleAction.go b/logic/service/fight/info/BattleAction.go index 44b283182..901708654 100644 --- a/logic/service/fight/info/BattleAction.go +++ b/logic/service/fight/info/BattleAction.go @@ -23,7 +23,6 @@ var PlayerOperations = enum.New[struct { type BattleAction struct { Priority EnumPlayerOperation //优先级本质上是action的itoa - //ramdom *random.RandomXS128 ctx context.Context } diff --git a/logic/service/fight/info/BattleInputSourceEntity.go b/logic/service/fight/info/BattleInputSourceEntity.go index a3a5df1f6..e27e1a9e0 100644 --- a/logic/service/fight/info/BattleInputSourceEntity.go +++ b/logic/service/fight/info/BattleInputSourceEntity.go @@ -4,7 +4,7 @@ import "context" type BattleInputSourceEntity struct { FightUserInfo - ctx context.Context + ctx context.Context //输入源的上下文 } // 新建一个宠物 diff --git a/logic/service/fight/info/battle_1v1.go b/logic/service/fight/info/battle_1v1.go index 0fa592a05..e419bd64c 100644 --- a/logic/service/fight/info/battle_1v1.go +++ b/logic/service/fight/info/battle_1v1.go @@ -1,7 +1,7 @@ package info import ( - "blazing/logic/service/fight/battle/random" + "blazing/common/utils/random" "context" "time" @@ -9,7 +9,7 @@ import ( type BattleContainer1V1 struct { BattleContext - ownerid uint32 + ownerid uint32 // 房主ID } // 返回房主信息 From cd229c1ca7547170755377dbc2a4c464950f5bec Mon Sep 17 00:00:00 2001 From: 1 <1@72wo.cn> Date: Mon, 25 Aug 2025 16:51:40 +0000 Subject: [PATCH 3/4] =?UTF-8?q?refactor(fight):=20=E6=B8=85=E7=90=86Battle?= =?UTF-8?q?PetEntity=E4=B8=AD=E7=9A=84=E5=BA=9F=E5=BC=83=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E5=92=8C=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- logic/service/fight/info/BattlePetEntity.go | 24 --------------------- 1 file changed, 24 deletions(-) diff --git a/logic/service/fight/info/BattlePetEntity.go b/logic/service/fight/info/BattlePetEntity.go index a6197eb1f..6a106c42e 100644 --- a/logic/service/fight/info/BattlePetEntity.go +++ b/logic/service/fight/info/BattlePetEntity.go @@ -58,30 +58,6 @@ type BattlePetEntity struct { skills [4]*BattleSkillEntity // 技能槽(最多4个技能) - // // 特殊属性 - // Perseverance int // 毅力值:抵消致命伤 - // Stubborn bool // 顽强特性 - // StubbornProbability int // 顽强触发概率 - // Revival bool // 回神特性 - // RevivalProbability int // 回神触发概率 - - // Definitely int // 必定命中概率 - // Dodge int // 闪避概率 - - // // 护盾相关 - // MaxShield int64 // 最大护盾值 - // Shield int64 // 当前护盾值 - // CountShield int // 次数盾 - // Level int64 - // // 属性变化回合 - // //petAttributeRound map[BattleRoundStarEffect]int // 属性变化类型 -> 剩余回合 - // petImmunityEffectIds map[int]int // 免疫效果ID -> 剩余回合 (-1表示永久) - // petImmunityBuffs map[string]int // 免疫buff效果ID -> 剩余回合 (-1表示永久) - - // IsDead bool // 是否死亡 - // otherRates map[DamageMultiplierZone]decimal.Decimal // 各伤害乘算区倍率,使用高精度decimal - // 战斗开始时拥有的特殊buff - //battleStartHavingBuffs []buff.BattleBuffInterface } // calculateRealValue 计算实际属性值根据状态变化计算实际值 From be5a0e144ff6a497e7f2d780725657d084d77475 Mon Sep 17 00:00:00 2001 From: 1 <1@72wo.cn> Date: Mon, 25 Aug 2025 18:10:45 +0000 Subject: [PATCH 4/4] =?UTF-8?q?"refactor(socket):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=8E=A9=E5=AE=B6=E6=96=AD=E5=BC=80=E8=BF=9E=E6=8E=A5=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E7=99=BB=E5=BD=95=E7=8A=B6=E6=80=81=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E5=88=B7=E6=80=AA=E9=80=BB=E8=BE=91?= =?UTF-8?q?"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/data/entity/Server.go | 360 ----------------------------------- common/socket/ServerEvent.go | 1 + logic/controller/map.go | 44 ++++- 3 files changed, 38 insertions(+), 367 deletions(-) delete mode 100644 common/data/entity/Server.go diff --git a/common/data/entity/Server.go b/common/data/entity/Server.go deleted file mode 100644 index 1b42ff354..000000000 --- a/common/data/entity/Server.go +++ /dev/null @@ -1,360 +0,0 @@ -package entity - -// import ( -// "context" -// "database/sql" -// "errors" -// "fmt" -// "log" -// "sync" -// "time" - -// ) - -// // Server 游戏服务器核心类,管理玩家、星球和游戏逻辑 -// type Server struct { -// players map[int64]*entity.Player -// planets map[int64]*planet.Planet -// mutex sync.RWMutex -// gameRepo repo.GameResourceRepo -// serverRepo repo.ServerRepo -// accountRepo repo.AccountRepo -// playerInfoRepo repo.PlayerInfoRepo -// playerItemRepo repo.PlayerItemInfoRepo -// petRepo repo.PetRepo -// } - -// // NewServer 创建新的游戏服务器实例 -// func NewServer( -// gameRepo repo.GameResourceRepo, -// serverRepo repo.ServerRepo, -// accountRepo repo.AccountRepo, -// playerInfoRepo repo.PlayerInfoRepo, -// playerItemRepo repo.PlayerItemInfoRepo, -// petRepo repo.PetRepo, -// ) *Server { -// s := &Server{ -// players: make(map[int64]*entity.Player), -// planets: make(map[int64]*planet.Planet), -// gameRepo: gameRepo, -// serverRepo: serverRepo, -// accountRepo: accountRepo, -// playerInfoRepo: playerInfoRepo, -// playerItemRepo: playerItemRepo, -// petRepo: petRepo, -// } -// s.initializePlanets() -// return s -// } - -// // initializePlanets 初始化所有星球 -// func (s *Server) initializePlanets() { -// maps := s.gameRepo.GetAllMaps() -// for _, config := range maps { -// planet := s.generatePlanet(config) -// s.planets[planet.GetId()] = planet -// } -// } - -// // generatePlanet 根据地图配置生成星球 -// func (s *Server) generatePlanet(config *mapInfo.MapXmlModel) *planet.Planet { -// entries := config.GetEntries() -// positions := make(map[int64]structs.Point) - -// if len(entries) == 0 { -// positions = make(map[int64]structs.Point) -// } else { -// for _, entry := range entries { -// positions[entry.GetFromMap()] = s.generatePoint(entry) -// } -// } - -// return planet.NewPlanet( -// s, -// int64(config.GetId()), -// config.GetName(), -// structs.Point{X: config.GetX(), Y: config.GetY()}, -// positions, -// s.gameRepo.CanMapRefresh(config.GetId()), -// ) -// } - -// // generatePoint 从入口配置生成点坐标 -// func (s *Server) generatePoint(xml *mapInfo.EntryXmlModel) structs.Point { -// return structs.Point{X: xml.GetPosX(), Y: xml.GetPosY()} -// } - -// // GetPlayer 获取玩家信息 -// func (s *Server) GetPlayer(accountID int64) (*entity.Player, error) { -// s.mutex.RLock() -// defer s.mutex.RUnlock() - -// player, exists := s.players[accountID] -// if !exists { -// return nil, errors.New("玩家不存在") -// } -// return player, nil -// } - -// // GetPlanet 获取星球信息 -// func (s *Server) GetPlanet(planetID int64) (*planet.Planet, error) { -// s.mutex.RLock() -// defer s.mutex.RUnlock() - -// planet, exists := s.planets[planetID] -// if !exists { -// return nil, errors.New("星球不存在") -// } -// return planet, nil -// } - -// // GetDefaultPlanet 获取默认星球 -// func (s *Server) GetDefaultPlanet() (*planet.Planet, error) { -// s.mutex.RLock() -// defer s.mutex.RUnlock() - -// planet, exists := s.planets[1] // 假设1是默认星球ID -// if !exists { -// return nil, errors.New("未找到默认星球") -// } -// return planet, nil -// } - -// // PlayerEnter 玩家加入服务器 -// func (s *Server) PlayerEnter(player *entity.Player) { -// s.mutex.Lock() -// defer s.mutex.Unlock() - -// s.players[player.GetAccountID()] = player -// } - -// // PlayerOffline 玩家离线处理 -// func (s *Server) PlayerOffline(player *entity.Player) { -// s.mutex.Lock() -// defer s.mutex.Unlock() - -// // 清理缓存会话数据 -// if err := s.accountRepo.RemoveSessionID(player.GetSessionID()); err != nil { -// log.Printf("清除会话ID失败: %v", err) -// } - -// // 清理登录绑定服务器 -// if err := s.serverRepo.CancelRecordAccount(player.GetAccountID()); err != nil { -// log.Printf("取消账号绑定失败: %v", err) -// } - -// // 从玩家列表中移除 -// delete(s.players, player.GetAccountID()) -// } - -// // BroadcastMessage 广播消息给所有在线玩家 -// func (s *Server) BroadcastMessage(message *net.OutboundMessage) { -// s.mutex.RLock() -// defer s.mutex.RUnlock() - -// for _, player := range s.players { -// if player.IsOnline() { -// player.SendMessage(message) -// } -// } -// } - -// // BroadcastMessageWithFilter 按条件广播消息给在线玩家 -// func (s *Server) BroadcastMessageWithFilter(message *net.OutboundMessage, filter func(*entity.Player) bool) { -// s.mutex.RLock() -// defer s.mutex.RUnlock() - -// for _, player := range s.players { -// if player.IsOnline() && filter(player) { -// player.SendMessage(message) -// } -// } -// } - -// // GeneratePetEntity 生成宠物实体 -// func (s *Server) GeneratePetEntity( -// playerID int64, -// petTypeID int, -// individualValue int16, -// nature int, -// abilityTypeEnum int, -// isShiny bool, -// level int, -// ) (*pet.PetEntity, error) { -// if level < 1 || level > 100 { -// return nil, fmt.Errorf("精灵等级必须在1到100之间, level: %d", level) -// } - -// petInfo, err := s.gameRepo.GetMonsterByID(petTypeID) -// if err != nil { -// return nil, fmt.Errorf("无效的精灵ID, pet_id: %d, 错误: %v", petTypeID, err) -// } - -// firstSkillInfo, err := s.gameRepo.GetPetFirstSkillID(petTypeID, level) -// if err != nil { -// return nil, fmt.Errorf("精灵没有初始技能, pet_id: %d, 错误: %v", petTypeID, err) -// } - -// zero := int16(0) - -// pet := pet.NewPetEntityBuilder() -// .WithAsset(petInfo) -// .WithLevelToExp(s.gameRepo.GetLevelToExp()) -// .WithPlayerID(playerID) -// .WithCapturePlayerID(playerID) -// .WithCaptureTime(time.Now().Unix()) -// .WithCaptureMap(0) // 假设0是默认地图ID -// .WithCaptureRect(0) // 假设0是默认区域 -// .WithCaptureLevel(level) -// .WithIndividualValue(individualValue) -// .WithNature(nature) -// .WithAbilityTypeEnum(abilityTypeEnum) -// .WithIsShiny(isShiny) -// .WithLevel(level) -// .WithCurrentExp(0) -// .WithEvHp(zero) -// .WithEvAttack(zero) -// .WithEvDefense(zero) -// .WithEvSpecialAttack(zero) -// .WithEvSpecialDefense(zero) -// .WithEvSpeed(zero) -// .WithSkill1ID(firstSkillInfo[0].GetId()) -// .WithSkill1Pp(firstSkillInfo[0].GetMaxPp()) -// .WithSkill2ID(firstSkillInfo[1].GetId()) -// .WithSkill2Pp(firstSkillInfo[1].GetMaxPp()) -// .WithSkill3ID(firstSkillInfo[2].GetId()) -// .WithSkill3Pp(firstSkillInfo[2].GetMaxPp()) -// .WithSkill4ID(firstSkillInfo[3].GetId()) -// .WithSkill4Pp(firstSkillInfo[3].GetMaxPp()) -// .WithIndividualGuarantee(0) -// .WithNatureGuarantee(0) -// .Build() - -// if err := s.CalculatePetPanel(pet); err != nil { -// return nil, err -// } - -// return pet, nil -// } - -// // CalculatePetPanel 计算宠物面板属性 -// func (s *Server) CalculatePetPanel(petEntity *pet.PetEntity) error { -// natureInfo, err := s.gameRepo.GetNatureInfoByID(petEntity.GetNature()) -// if err != nil { -// return fmt.Errorf("无效的性格ID, nature: %d, 错误: %v", petEntity.GetNature(), err) -// } - -// hp := util.CalculatePetHPPanelSize( -// petEntity.GetAsset().GetHp(), -// petEntity.GetIndividualValue(), -// petEntity.GetLevel(), -// petEntity.GetEvHp(), -// ) - -// attack := util.CalculatePetPanelSize( -// petEntity.GetAsset().GetAtk(), -// petEntity.GetIndividualValue(), -// petEntity.GetLevel(), -// petEntity.GetEvHp(), -// natureInfo.GetAttackCorrect(), -// ) - -// defense := util.CalculatePetPanelSize( -// petEntity.GetAsset().GetDef(), -// petEntity.GetIndividualValue(), -// petEntity.GetLevel(), -// petEntity.GetEvHp(), -// natureInfo.GetDefenseCorrect(), -// ) - -// specialAttack := util.CalculatePetPanelSize( -// petEntity.GetAsset().GetSpAtk(), -// petEntity.GetIndividualValue(), -// petEntity.GetLevel(), -// petEntity.GetEvHp(), -// natureInfo.GetSaCorrect(), -// ) - -// specialDefense := util.CalculatePetPanelSize( -// petEntity.GetAsset().GetSpDef(), -// petEntity.GetIndividualValue(), -// petEntity.GetLevel(), -// petEntity.GetEvHp(), -// natureInfo.GetSdCorrect(), -// ) - -// speed := util.CalculatePetPanelSize( -// petEntity.GetAsset().GetSpd(), -// petEntity.GetIndividualValue(), -// petEntity.GetLevel(), -// petEntity.GetEvHp(), -// natureInfo.GetSpeedCorrect(), -// ) - -// petEntity.SetMaxHp(hp) -// petEntity.SetCurrentHp(hp) -// petEntity.SetAttack(attack) -// petEntity.SetDefense(defense) -// petEntity.SetSpecialAttack(specialAttack) -// petEntity.SetSpecialDefense(specialDefense) -// petEntity.SetSpeed(speed) - -// return nil -// } - -// // SavePlayer 保存玩家信息到数据库 -// func (s *Server) SavePlayer(player *entity.Player) (bool, error) { -// ctx := context.Background() -// tx, err := s.playerInfoRepo.BeginTransaction(ctx) -// if err != nil { -// return false, fmt.Errorf("开始事务失败: %v", err) -// } -// defer func() { -// if r := recover(); r != nil { -// tx.Rollback() -// log.Printf("保存玩家时发生panic: %v", r) -// } else if err != nil { -// tx.Rollback() -// } else { -// tx.Commit() -// } -// }() - -// playerID := player.GetGameID() -// pets := player.GetPetBag().GetUsedPets() -// items := player.GetItemBag().GetItems() - -// // 保存玩家信息 -// if err := s.playerInfoRepo.Save(ctx, tx, player); err != nil { -// return false, fmt.Errorf("保存玩家信息失败: %v", err) -// } - -// // 保存精灵信息 -// if err := s.petRepo.SaveAll(ctx, tx, playerID, pets); err != nil { -// return false, fmt.Errorf("保存精灵信息失败: %v", err) -// } - -// // 保存玩家背包信息 -// if err := s.playerItemRepo.SaveAll(ctx, tx, playerID, items); err != nil { -// return false, fmt.Errorf("保存背包信息失败: %v", err) -// } - -// return true, nil -// } - -// // Destroy 销毁服务器,清理资源 -// func (s *Server) Destroy() error { -// // 保存所有玩家数据 -// s.mutex.RLock() -// for _, player := range s.players { -// go func(p *entity.Player) { -// if _, err := s.SavePlayer(p); err != nil { -// log.Printf("保存玩家 %d 数据失败: %v", p.GetAccountID(), err) -// } -// }(player) -// } -// s.mutex.RUnlock() - -// log.Println("Destroying server ...") -// return nil -// } diff --git a/common/socket/ServerEvent.go b/common/socket/ServerEvent.go index 0de041717..8cef8a359 100644 --- a/common/socket/ServerEvent.go +++ b/common/socket/ServerEvent.go @@ -50,6 +50,7 @@ func (s *Server) OnClose(c gnet.Conn, _ error) (action gnet.Action) { t := v.GetPlayer() if t != nil { glog.Debug(context.Background(), t.UserID, "断开连接") + t.IsLogin = false cool.Mainplayer.Delete(t.UserID) share.ShareManager.DeleteUserOnline(t.UserID) //设置用户登录服务器 } diff --git a/logic/controller/map.go b/logic/controller/map.go index 203f55dd1..425ecbcb3 100644 --- a/logic/controller/map.go +++ b/logic/controller/map.go @@ -42,7 +42,7 @@ func (h *Controller) MapEnter(data *maps.InInfo, c *entity.Player) (result *maps case <-ticker.C: // 刷新当前地图的怪物 if !c.IsFighting && c.MapId != 0 { - spawnMonsters(currentMap, c) + spawnMonsters(c) } } @@ -85,28 +85,58 @@ func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *entity.Play } // 刷怪具体实现 -func spawnMonsters(mapID int, c *entity.Player) { +func spawnMonsters(c *entity.Player) { // 获取当前地图的怪物配置 - if mservice.NewMonsterService().GetId(c.MapId) == 0 { + if c == nil || mservice.NewMonsterService().GetId(c.MapId) == 0 { //用户离线 return } + if !c.IsLogin { + defer func() { + + if c.StopChan != nil { + close(c.StopChan) + c.StopChan = nil + } + }() + } // 创建数据包 tt := handler.NewTomeeHeader(2004, c.UserID) + t1 := genMonster(c.MapId) + c.SendPack(tt.Pack(&t1)) +} + +func genMonster(id uint32) maps.OgreInfo { // 设置怪物信息 t1 := maps.OgreInfo{} - //copy(t1.Data[:], monsterConfig) // 使用地图对应的怪物配置 + var localMenu = make([]int, 0) + for i := 7; i <= 448; i++ { + if bitsCount(i) == 3 { + localMenu = append(localMenu, i) + } + } + for i := 0; i < 3; i++ { ttt := maps.OgrePetInfo{} - ttt.Id = mservice.NewMonsterService().GetId(c.MapId) + ttt.Id = mservice.NewMonsterService().GetId(id) ttt.Shiny = uint32(i + 1) //t1.Data[i] = mservice.NewMonsterService().GetId(c.MapId) t1.Data[i] = ttt } - // 发送数据包 - c.SendPack(tt.Pack(&t1)) + + return t1 +} + +// 计算整数的二进制1的个数(对应Java的Integer.bitCount) +func bitsCount(n int) int { + count := 0 + for n > 0 { + count += n & 1 + n >>= 1 + } + return count }