feat(rpc): 优化客户端连接管理,使用 sync.Map 替代普通 map
将 `Clientmap` 从普通 map 改为 `sync.Map`,提升并发安全性。新增 `addClient` 和 `getClient` 方法封装存取逻辑,并在多处调用点进行了替换。 fix(fight): 修复战斗逻辑中技能ID与攻击时间字段引用错误 将 `attacker.AttackValue.SkillID` 和 `attacker.AttackValue.AttackTime` 的访问方式修正为正确的字段路径。 refactor(fight): 调整战斗结束信息处理流程 合并 `FightOverInfo` 结构到 `FightC` 中,简化广播发送逻辑,统一通过 `f.FightOverInfo` 发送战斗结果。 refactor(effect): 修改效果叠加判断逻辑并增强健壮性 更新效果节点比较方法,增加参数匹配检查以支持更精确的效果识别;同时添加 `equalInts` 工具函数用于数组内容对比。
This commit is contained in:
@@ -20,6 +20,7 @@ func GetServerInfoList() []ServerInfo {
|
|||||||
var ret1 []ServerInfo
|
var ret1 []ServerInfo
|
||||||
ip, _ := service.NewBaseSysParamService().DataByKey(context.Background(), "server_ip")
|
ip, _ := service.NewBaseSysParamService().DataByKey(context.Background(), "server_ip")
|
||||||
testip, _ := service.NewBaseSysParamService().DataByKey(context.Background(), "test_ip")
|
testip, _ := service.NewBaseSysParamService().DataByKey(context.Background(), "test_ip")
|
||||||
|
|
||||||
for _, v := range ret {
|
for _, v := range ret {
|
||||||
tt := newServerInfo()
|
tt := newServerInfo()
|
||||||
tt.OnlineID = uint32(v.OnlineID)
|
tt.OnlineID = uint32(v.OnlineID)
|
||||||
@@ -30,7 +31,8 @@ func GetServerInfoList() []ServerInfo {
|
|||||||
tt.IP = testip
|
tt.IP = testip
|
||||||
}
|
}
|
||||||
tt.Port = v.Port
|
tt.Port = v.Port
|
||||||
t, ok := Clientmap[v.Port]
|
|
||||||
|
t, ok := getClient(v.Port)
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
cool.Loger.Info(context.TODO(), "服务器假踢人")
|
cool.Loger.Info(context.TODO(), "服务器假踢人")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package rpc
|
|||||||
import (
|
import (
|
||||||
"blazing/common/data/share"
|
"blazing/common/data/share"
|
||||||
"blazing/cool"
|
"blazing/cool"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"blazing/modules/base/service"
|
"blazing/modules/base/service"
|
||||||
"context"
|
"context"
|
||||||
@@ -18,7 +19,26 @@ import (
|
|||||||
|
|
||||||
var rpcport = gconv.String(cool.Config.RPC)
|
var rpcport = gconv.String(cool.Config.RPC)
|
||||||
|
|
||||||
var Clientmap = make(map[uint16]*ClientHandler) //客户端map
|
// 定义改为sync.Map
|
||||||
|
var Clientmap sync.Map
|
||||||
|
|
||||||
|
// 存值示例
|
||||||
|
func addClient(id uint16, client *ClientHandler) {
|
||||||
|
// 普通map:Clientmap[id] = client
|
||||||
|
Clientmap.Store(id, client) // sync.Map存值
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取值示例
|
||||||
|
func getClient(id uint16) (*ClientHandler, bool) {
|
||||||
|
// 普通map:client, ok := Clientmap[id]
|
||||||
|
val, ok := Clientmap.Load(id) // sync.Map取值
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
// 类型断言(确保value是*ClientHandler)
|
||||||
|
client, ok := val.(*ClientHandler)
|
||||||
|
return client, ok
|
||||||
|
}
|
||||||
|
|
||||||
type ClientHandler struct {
|
type ClientHandler struct {
|
||||||
KickPerson func(uint32) error //踢人,这里是返回具体的logic
|
KickPerson func(uint32) error //踢人,这里是返回具体的logic
|
||||||
@@ -37,7 +57,8 @@ func (h *ServerHandler) Kick(ctx context.Context, userid uint32) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("user not found", err)
|
return fmt.Errorf("user not found", err)
|
||||||
}
|
}
|
||||||
cl, ok := Clientmap[useid1]
|
|
||||||
|
cl, ok := getClient(useid1)
|
||||||
if ok {
|
if ok {
|
||||||
err := cl.KickPerson(userid) //实现指定服务器踢人
|
err := cl.KickPerson(userid) //实现指定服务器踢人
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -57,11 +78,11 @@ func (h *ServerHandler) RegisterLogic(ctx context.Context, id, port uint16) erro
|
|||||||
return fmt.Errorf("no reverse client")
|
return fmt.Errorf("no reverse client")
|
||||||
}
|
}
|
||||||
t, _ := blservice.NewLoginServiceService().GetServerID(id)
|
t, _ := blservice.NewLoginServiceService().GetServerID(id)
|
||||||
aa, ok := Clientmap[t]
|
aa, ok := getClient(t)
|
||||||
if ok && aa != nil { //如果已经存在且这个端口已经被存过
|
if ok && aa != nil { //如果已经存在且这个端口已经被存过
|
||||||
aa.QuitSelf(0)
|
aa.QuitSelf(0)
|
||||||
}
|
}
|
||||||
Clientmap[port] = &revClient
|
addClient(port, &revClient)
|
||||||
|
|
||||||
//Refurh()
|
//Refurh()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
|
|||||||
-1,
|
-1,
|
||||||
0, //野怪没特性
|
0, //野怪没特性
|
||||||
0,
|
0,
|
||||||
2)
|
bm.Lv)
|
||||||
|
|
||||||
mo.Level = uint32(bm.Lv)
|
// mo.Level = uint32(bm.Lv)
|
||||||
mo.CalculatePetPane()
|
mo.CalculatePetPane()
|
||||||
mo.Hp = uint32(bm.Hp)
|
mo.Hp = uint32(bm.Hp)
|
||||||
mo.MaxHp = uint32(bm.Hp)
|
mo.MaxHp = uint32(bm.Hp)
|
||||||
|
|||||||
@@ -89,15 +89,11 @@ func (u *UseItemAction) Priority() int {
|
|||||||
// EscapeAction 逃跑的战斗动作
|
// EscapeAction 逃跑的战斗动作
|
||||||
type EscapeAction struct {
|
type EscapeAction struct {
|
||||||
BaseAction
|
BaseAction
|
||||||
Reason info.FightOverInfo
|
Reason info.EnumBattleOverReason
|
||||||
Our common.PlayerI
|
Our common.PlayerI
|
||||||
Opp common.PlayerI
|
Opp common.PlayerI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EscapeAction) GetInfo() info.FightOverInfo {
|
|
||||||
return e.Reason
|
|
||||||
}
|
|
||||||
|
|
||||||
// Priority 返回动作优先级
|
// Priority 返回动作优先级
|
||||||
func (e *EscapeAction) Priority() int {
|
func (e *EscapeAction) Priority() int {
|
||||||
return int(PlayerOperations.Escape)
|
return int(PlayerOperations.Escape)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func newEffectStat(targetOpponent bool) input.Effect {
|
|||||||
e := &EffectStat{
|
e := &EffectStat{
|
||||||
Etype: targetOpponent,
|
Etype: targetOpponent,
|
||||||
}
|
}
|
||||||
e.MaxStack(-1) // 无限叠加
|
//e.MaxStack(-1) // 无限叠加
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
input.InitEffect(input.EffectType.Skill, 9, &Effect9{
|
t := &Effect9{
|
||||||
EffectNode: node.EffectNode{},
|
EffectNode: node.EffectNode{},
|
||||||
})
|
}
|
||||||
|
t.Duration(-1)
|
||||||
|
t.MaxStack(-1)
|
||||||
|
input.InitEffect(input.EffectType.Skill, 9, t)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type FightC struct {
|
|||||||
First *input.Input
|
First *input.Input
|
||||||
Second *input.Input
|
Second *input.Input
|
||||||
closefight bool
|
closefight bool
|
||||||
|
info.FightOverInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FightC) CanEscape() bool {
|
func (f *FightC) CanEscape() bool {
|
||||||
@@ -274,8 +275,8 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
|
|||||||
//技能miss+效果生效 这里属于强制改命中效果,但是正常来说,技能miss掉后效果也应该失效
|
//技能miss+效果生效 这里属于强制改命中效果,但是正常来说,技能miss掉后效果也应该失效
|
||||||
//技能失效+效果失效
|
//技能失效+效果失效
|
||||||
// 记录技能信息
|
// 记录技能信息
|
||||||
attacker.AttackValue.SkillID = uint32(a.ID) //获取技能ID
|
attacker.SkillID = uint32(a.ID) //获取技能ID
|
||||||
if attacker.AttackValue.AttackTime > 0 { //如果命中
|
if attacker.AttackTime > 0 { //如果命中
|
||||||
|
|
||||||
attacker.UseSkill(defender, a) //暴击计算
|
attacker.UseSkill(defender, a) //暴击计算
|
||||||
attacker.AttackValue.IsCritical = a.Crit
|
attacker.AttackValue.IsCritical = a.Crit
|
||||||
@@ -366,6 +367,7 @@ func copyskill(t *action.SelectSkillAction) *action.SelectSkillAction {
|
|||||||
func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||||
|
|
||||||
if f.closefight { //战斗结束
|
if f.closefight { //战斗结束
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 伤害值
|
// 伤害值
|
||||||
@@ -526,13 +528,8 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
|||||||
} else {
|
} else {
|
||||||
WinnerId = f.Second.Player.GetInfo().UserID
|
WinnerId = f.Second.Player.GetInfo().UserID
|
||||||
}
|
}
|
||||||
defer f.Broadcast(func(ff *input.Input) {
|
f.FightOverInfo.WinnerId = WinnerId
|
||||||
//todo 将血量和技能pp传回enterturn
|
|
||||||
|
|
||||||
ff.Player.SendFightEndInfo(info.FightOverInfo{
|
|
||||||
WinnerId: WinnerId,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
f.closefight = true
|
f.closefight = true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -261,11 +261,14 @@ type ReadyFightPetInfo struct {
|
|||||||
|
|
||||||
// FightOverInfo 战斗结束信息结构体 2506
|
// FightOverInfo 战斗结束信息结构体 2506
|
||||||
type FightOverInfo struct {
|
type FightOverInfo struct {
|
||||||
|
//0 正常结束
|
||||||
//1=isPlayerLost 对方玩家退出
|
//1=isPlayerLost 对方玩家退出
|
||||||
// 2=isOvertime 正常对战结束?有质疑
|
// 2=isOvertime 超时
|
||||||
// 3=isDraw 双方平手
|
// 3=isDraw 双方平手
|
||||||
// 4=isSysError 系统错误
|
// 4=isSysError 系统错误
|
||||||
// 5=isNpcEscape 精灵主动逃跑
|
// 5=isNpcEscape 精灵主动逃跑
|
||||||
|
|
||||||
|
//7 切磋结束
|
||||||
Reason EnumBattleOverReason // 固定值0
|
Reason EnumBattleOverReason // 固定值0
|
||||||
WinnerId uint32 // 胜者的米米号 野怪为0
|
WinnerId uint32 // 胜者的米米号 野怪为0
|
||||||
TwoTimes uint32 // 双倍经验剩余次数
|
TwoTimes uint32 // 双倍经验剩余次数
|
||||||
|
|||||||
@@ -294,6 +294,9 @@ func (i *Input) GetAction(opp *Input) {
|
|||||||
allSkills := make([]skillWithDamage, 0, len(skills))
|
allSkills := make([]skillWithDamage, 0, len(skills))
|
||||||
|
|
||||||
for _, s := range skills {
|
for _, s := range skills {
|
||||||
|
if s == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// 计算技能对对方的伤害(假设CalculatePower返回伤害值,或需从技能中获取)
|
// 计算技能对对方的伤害(假设CalculatePower返回伤害值,或需从技能中获取)
|
||||||
damage := i.CalculatePower(opp, s)
|
damage := i.CalculatePower(opp, s)
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ func (c *Input) GetProp(id int, istue bool) int {
|
|||||||
func (c *Input) GetEffect(etype EnumEffectType, id int) Effect {
|
func (c *Input) GetEffect(etype EnumEffectType, id int) Effect {
|
||||||
var ret []Effect
|
var ret []Effect
|
||||||
for _, v := range c.Effects {
|
for _, v := range c.Effects {
|
||||||
if v.ID() == id &&v.Alive(){
|
if v.ID() == id+int(etype) && v.Alive() {
|
||||||
ret = append(ret, v)
|
ret = append(ret, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +99,21 @@ func (c *Input) GetCurrAttr(id int) *model.PetInfo {
|
|||||||
//todo 获取后GetEffect
|
//todo 获取后GetEffect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 比较两个[]int是否内容相等
|
||||||
|
func equalInts(a, b []int) bool {
|
||||||
|
// 先判断长度是否相等
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 逐个比较元素
|
||||||
|
for i := range a {
|
||||||
|
if a[i] != b[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Input) AddEffect(e Effect) {
|
func (c *Input) AddEffect(e Effect) {
|
||||||
|
|
||||||
//todo 免疫
|
//todo 免疫
|
||||||
@@ -106,19 +121,25 @@ func (c *Input) AddEffect(e Effect) {
|
|||||||
fmt.Println("产生回合数", e.ID(), e.Duration())
|
fmt.Println("产生回合数", e.ID(), e.Duration())
|
||||||
// 如果已有同 ID 的效果,尝试叠加
|
// 如果已有同 ID 的效果,尝试叠加
|
||||||
for _, v := range c.Effects {
|
for _, v := range c.Effects {
|
||||||
if v.ID() == e.ID() && v.Alive() {
|
//如果效果相同,id相同,参数相同,就是同一个,确认是否可以叠加,正常来说本身就可以共存
|
||||||
|
//衰弱本身参数也是相同的,区别只是传入的回合数不一样和层数不一样
|
||||||
|
|
||||||
if v.MaxStack() > 0 {
|
if v.ID() == e.ID() &&
|
||||||
e.Alive(false) //取消之前效果
|
v.Alive() &&
|
||||||
if v.Stack() <= v.MaxStack() { //如果小于最大叠层,状态可以叠层
|
equalInts(v.GetArgs(), e.GetArgs()) &&
|
||||||
e.SetArgs(v.GetInput(), v.GetArgs()...) //参数输入
|
v.MaxStack() != 0 { //如果层数可以叠加或者是无限层数
|
||||||
e.Stack(v.Stack() + e.Stack()) //获取到当前叠层数然后叠加
|
|
||||||
//v.Duration(e.Duration()) //回合数覆盖
|
///e.Alive(false) //取消之前效果
|
||||||
}
|
if v.Stack() <= v.MaxStack() { //如果小于最大叠层,状态可以叠层
|
||||||
|
|
||||||
|
e.Stack(v.Stack() + e.Stack()) //获取到当前叠层数然后叠加
|
||||||
|
//这里直接返回,不再继续执行后续效果,因为这里是可以叠加的效果
|
||||||
|
//v.Duration(e.Duration()) //回合数覆盖
|
||||||
|
|
||||||
}
|
}
|
||||||
c.Effects = append(c.Effects, e)
|
|
||||||
return
|
return
|
||||||
|
// c.Effects = append(c.Effects, e)
|
||||||
|
//return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ func (f *FightC) battleLoop() {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
if f.closefight {
|
if f.closefight {
|
||||||
|
f.Broadcast(func(ff *input.Input) {
|
||||||
|
//todo 将血量和技能pp传回enterturn
|
||||||
|
|
||||||
|
ff.Player.SendFightEndInfo(f.FightOverInfo)
|
||||||
|
|
||||||
|
})
|
||||||
close(f.actionChan)
|
close(f.actionChan)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -119,9 +125,9 @@ func (f *FightC) resolveRound(p1Action, p2Action action.BattleActionI) {
|
|||||||
switch a := b1.(type) {
|
switch a := b1.(type) {
|
||||||
|
|
||||||
case *action.EscapeAction:
|
case *action.EscapeAction:
|
||||||
f.Broadcast(func(ff *input.Input) {
|
f.FightOverInfo.WinnerId = b2.GetPlayerID() //对方胜利
|
||||||
ff.Player.SendFightEndInfo(a.Reason)
|
f.FightOverInfo.Reason = a.Reason
|
||||||
})
|
|
||||||
f.closefight = true
|
f.closefight = true
|
||||||
|
|
||||||
case *action.ActiveSwitchAction:
|
case *action.ActiveSwitchAction:
|
||||||
@@ -154,7 +160,9 @@ func (f *FightC) handleItemAction(a *action.UseItemAction, other action.BattleAc
|
|||||||
CatchTime: uint32(f.Opp.CurrentPet.Info.CatchTime),
|
CatchTime: uint32(f.Opp.CurrentPet.Info.CatchTime),
|
||||||
PetId: uint32(f.Opp.CurrentPet.ID),
|
PetId: uint32(f.Opp.CurrentPet.ID),
|
||||||
})
|
})
|
||||||
our.SendFightEndInfo(info.FightOverInfo{WinnerId: f.ownerID})
|
//f.WinnerId = 0 //捕捉成功不算胜利
|
||||||
|
f.Reason = 6
|
||||||
|
|
||||||
f.closefight = true
|
f.closefight = true
|
||||||
} else {
|
} else {
|
||||||
our.CatchPetInfo(info.CatchMonsterOutboundInfo{})
|
our.CatchPetInfo(info.CatchMonsterOutboundInfo{})
|
||||||
|
|||||||
@@ -31,17 +31,9 @@ func (f *FightC) Compare(a, b action.BattleActionI) (action.BattleActionI, actio
|
|||||||
func (f *FightC) Over(c common.PlayerI, res info.EnumBattleOverReason) {
|
func (f *FightC) Over(c common.PlayerI, res info.EnumBattleOverReason) {
|
||||||
ret := &action.EscapeAction{
|
ret := &action.EscapeAction{
|
||||||
BaseAction: action.NewBaseAction(c.GetInfo().UserID),
|
BaseAction: action.NewBaseAction(c.GetInfo().UserID),
|
||||||
Reason: info.FightOverInfo{
|
Reason: res,
|
||||||
|
|
||||||
Reason: res,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
if c.GetInfo().UserID == f.ownerID {
|
|
||||||
ret.Reason.WinnerId = f.Opp.Player.GetInfo().UserID
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ret.Reason.WinnerId = f.Our.Player.GetInfo().UserID
|
|
||||||
}
|
|
||||||
f.actionChan <- ret
|
f.actionChan <- ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
public/login
BIN
public/login
Binary file not shown.
Reference in New Issue
Block a user