From 6979b7018d6551d70acd2facac39ae70eb9b6a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <1@72wo.cn> Date: Sat, 15 Nov 2025 15:22:58 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(space):=20=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E5=AE=89=E5=85=A8map=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E4=BB=A5=E6=8F=90=E5=8D=87=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将原来基于`utils.ConcurrentMap`的玩家存储结构替换为 `github.com/mhmtszr/concurrent-swiss-map`提供的`CsMap`, 以获得更高效的并发读写能力。 同时修改了相关API调用方式: - `Set` 改为 `Store` - `Remove` 改为 `Delete` - `IterCb` 改为 `Range`,并支持提前终止迭代 - `Items()` 不再使用 此外,调整了部分业务逻辑中对玩家列表遍历的方式, 确保在发送网络包后及时跳出循环,避免不必要的操作。 新增战斗类型处理函数`PET_King`用于处理宠物王相关的 战斗请求,并修复了`PET_MELEE`方法中的逻辑问题。 更新了go.mod和go.sum引入新的依赖库。 ``` --- common/utils/concurrent_map.go | 7 ++-- logic/controller/CreatePlayer.go | 3 +- logic/controller/fight_pvp_king.go | 32 +++++++++++++++++-- logic/controller/item.go | 3 +- logic/controller/login.go | 6 ++-- logic/controller/map.go | 9 +++--- logic/controller/user.go | 13 +++++--- logic/go.mod | 1 + logic/go.sum | 4 +++ logic/service/fight/cmd.go | 7 ++++ .../service/fight/effect/EffectAttackMiss.go | 2 +- .../effect/EffectPhysicalAttackAddStatus.go | 5 +-- logic/service/maps/mapin.go | 8 +++-- logic/service/maps/mapout.go | 3 +- logic/service/maps/walk.go | 3 +- logic/service/pet/pet.go | 8 +++-- logic/service/player/fight.go | 19 +++++------ logic/service/player/player.go | 8 +++-- logic/service/space/space.go | 24 ++++++++++---- 19 files changed, 117 insertions(+), 48 deletions(-) diff --git a/common/utils/concurrent_map.go b/common/utils/concurrent_map.go index e12e3ccc2..efc7c06a3 100644 --- a/common/utils/concurrent_map.go +++ b/common/utils/concurrent_map.go @@ -281,7 +281,7 @@ func (m ConcurrentMap[K, V]) Items() map[K]V { // maps. RLock is held for all calls for a given shard // therefore callback sess consistent view of a shard, // but not across the shards -type IterCb[K comparable, V any] func(key K, v V) +type IterCb[K comparable, V any] func(key K, v V) bool // Callback based iterator, cheapest way to read // all elements in a map. @@ -290,7 +290,10 @@ func (m ConcurrentMap[K, V]) IterCb(fn IterCb[K, V]) { shard := (m.shards)[idx] shard.RLock() for key, value := range shard.items { - fn(key, value) + + if !fn(key, value) { + break + } } shard.RUnlock() } diff --git a/logic/controller/CreatePlayer.go b/logic/controller/CreatePlayer.go index a98924c5a..f5dbf434f 100644 --- a/logic/controller/CreatePlayer.go +++ b/logic/controller/CreatePlayer.go @@ -30,8 +30,9 @@ func (h *Controller) ChangePlayerName(data *user.ChangePlayerNameInboundInfo, c UserID: c.Info.UserID, } - space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, player common.PlayerI) { + space.GetSpace(c.Info.MapID).User.Range(func(playerID uint32, player common.PlayerI) bool { player.SendPack(data.Head.Pack(&result)) + return false }) return result, 0 diff --git a/logic/controller/fight_pvp_king.go b/logic/controller/fight_pvp_king.go index c680250b9..312b36032 100644 --- a/logic/controller/fight_pvp_king.go +++ b/logic/controller/fight_pvp_king.go @@ -17,9 +17,37 @@ func (h Controller) PET_MELEE(data *fight.StartPetWarInboundInfo, c *player.Play c.PVPinfo = &info.PVPinfo{ Mode: info.BattleMode.PET_MELEE, Status: info.BattleStatus.FIGHT_WITH_PLAYER} - g := c.PET_MELEE() + g := c.Pet_joinFight() if g != nil { - fight.NewFight(info.BattleMode.PET_MELEE, info.BattleStatus.FIGHT_WITH_PLAYER, c.PET_MELEE(), c) ///开始对战,房主方以及被邀请方 + fight.NewFight(info.BattleMode.PET_MELEE, info.BattleStatus.FIGHT_WITH_PLAYER, g, c) ///开始对战,房主方以及被邀请方 + } + + return +} +func (h Controller) PET_King(data *fight.PetKingJoinInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { + if !c.CanFight() { + return nil, errorcode.ErrorCodes.ErrPokemonNotEligible + } + + c.PVPinfo = &info.PVPinfo{ + + Status: info.BattleStatus.FIGHT_WITH_PLAYER} + + switch data.Type { + case 5: + c.PVPinfo.Mode = info.BattleMode.SINGLE_MODE + case 6: + c.PVPinfo.Mode = info.BattleMode.MULTI_MODE + } + g := c.Pet_joinFight() + if g != nil { + switch data.Type { + case 5: + fight.NewFight(info.BattleMode.SINGLE_MODE, info.BattleStatus.FIGHT_WITH_PLAYER, g, c) ///开始对战,房主方以及被邀请方 + case 6: + fight.NewFight(info.BattleMode.MULTI_MODE, info.BattleStatus.FIGHT_WITH_PLAYER, g, c) ///开始对战,房主方以及被邀请方 + } + } return diff --git a/logic/controller/item.go b/logic/controller/item.go index 5778ba405..d48b29eb4 100644 --- a/logic/controller/item.go +++ b/logic/controller/item.go @@ -76,10 +76,11 @@ func (h Controller) ChangePlayerCloth(data *item.ChangePlayerClothInboundInfo, c result.ClothList = append(result.ClothList, model.PeopleItemInfo{ID: v, Level: 1}) } c.Info.Clothes = result.ClothList - space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, player common.PlayerI) { + space.GetSpace(c.Info.MapID).User.Range(func(playerID uint32, player common.PlayerI) bool { // fmt.Println("ChangePlayerCloth", playerID, data.Head.Pack(result)) data.Head.Result = 0 player.SendPack(data.Head.Pack(result)) + return false }) return nil, -1 diff --git a/logic/controller/login.go b/logic/controller/login.go index 801c94e1f..e10db0088 100644 --- a/logic/controller/login.go +++ b/logic/controller/login.go @@ -106,11 +106,11 @@ func (h *Controller) Login(data *user.MAIN_LOGIN_IN, c gnet.Conn) (result *user. //copier.Copy(t.Info, tt) t1 := player.NewTomeeHeader(2001, t.Info.UserID) - space.GetSpace(t.Info.MapID).User.IterCb(func(playerID uint32, player common.PlayerI) { + space.GetSpace(t.Info.MapID).User.Range(func(playerID uint32, player common.PlayerI) bool { player.SendPack(t1.Pack(tt)) - + return false }) - space.GetSpace(t.Info.MapID).User.Set(t.Info.UserID, t) + space.GetSpace(t.Info.MapID).User.Store(t.Info.UserID, t) }() return result, 0 diff --git a/logic/controller/map.go b/logic/controller/map.go index 5ae3afa21..9e06f19a9 100644 --- a/logic/controller/map.go +++ b/logic/controller/map.go @@ -14,8 +14,8 @@ import ( func (h *Controller) MapEnter(data *maps.InInfo, c *player.Player) (result *maps.OutInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 - c.Info.MapID = data.MapId //登录地图 - space.GetSpace(c.Info.MapID).User.Set(c.Info.UserID, c) //添加玩家 + c.Info.MapID = data.MapId //登录地图 + space.GetSpace(c.Info.MapID).User.Store(c.Info.UserID, c) //添加玩家 result = maps.NewOutInfo() c.Info.Pos = data.Point @@ -39,7 +39,7 @@ func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player) c.Canmon = false c.Changemap = true //可以刷怪 data.Broadcast(c.Info.MapID, space.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播 - space.GetSpace(c.Info.MapID).User.Remove(c.Info.UserID) + space.GetSpace(c.Info.MapID).User.Delete(c.Info.UserID) // 如果有正在运行的刷怪协程,发送停止信号 c.Info.MapID = 0 // 重置当前地图 @@ -49,11 +49,12 @@ func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *player.Play result = &maps.ListMapPlayerOutboundInfo{} result.Player = make([]maps.OutInfo, 0) - space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, player common.PlayerI) { + space.GetSpace(c.Info.MapID).User.Range(func(playerID uint32, player common.PlayerI) bool { result1 := maps.NewOutInfo() copier.CopyWithOption(result1, player.GetInfo(), copier.Option{DeepCopy: true}) result.Player = append(result.Player, *result1) result.Player = LastFourElements(result.Player) + return false }) c.Canmon = true //可以刷怪 diff --git a/logic/controller/user.go b/logic/controller/user.go index a76c112be..6e98d8bb2 100644 --- a/logic/controller/user.go +++ b/logic/controller/user.go @@ -37,7 +37,7 @@ func (h Controller) UserMoreInfo(data *user.MoreUserInfoInboundInfo, c *player.P func (h Controller) Aimat(data *user.AimatInboundInfo, c *player.Player) (result *user.AimatOutboundInfo, err errorcode.ErrorCode) { - defer space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, player common.PlayerI) { + defer space.GetSpace(c.Info.MapID).User.Range(func(playerID uint32, player common.PlayerI) bool { ret := &user.AimatOutboundInfo{ ItemId: data.ItemId, @@ -47,14 +47,14 @@ func (h Controller) Aimat(data *user.AimatInboundInfo, c *player.Player) (result } data.Head.Result = 0 player.SendPack(data.Head.Pack(ret)) - + return false }) return nil, -1 } func (h Controller) Chat(data *user.ChatInboundInfo, c *player.Player) (result *user.ChatOutboundInfo, err errorcode.ErrorCode) { - defer space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, v common.PlayerI) { + defer space.GetSpace(c.Info.MapID).User.Range(func(playerID uint32, v common.PlayerI) bool { result = &user.ChatOutboundInfo{ Message: string([]byte(data.Message)[:data.MessageLen-1]), @@ -64,6 +64,7 @@ func (h Controller) Chat(data *user.ChatInboundInfo, c *player.Player) (result * result.Message = cool.Filter.Replace(result.Message, '*') data.Head.Result = 0 v.SendPack(data.Head.Pack(result)) + return false }) return nil, -1 @@ -76,7 +77,7 @@ func (h Controller) ChangePlayerColor(data *user.ChangeColorInboundInfo, c *play c.Info.Color = data.Color c.Info.Texture = 0 - defer space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, v common.PlayerI) { + defer space.GetSpace(c.Info.MapID).User.Range(func(playerID uint32, v common.PlayerI) bool { data.Head.Result = 0 result = &user.ChangeColorOutboundInfo{ UserId: c.Info.UserID, @@ -85,6 +86,7 @@ func (h Controller) ChangePlayerColor(data *user.ChangeColorInboundInfo, c *play Texture: c.Info.Texture, } v.SendPack(data.Head.Pack(result)) + return false }) return nil, -1 @@ -95,7 +97,7 @@ func (h Controller) ChangePlayerDoodle(data *user.ChangeDoodleInboundInfo, c *pl } c.Info.Texture = data.Id c.Info.Color = data.Color - defer space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, v common.PlayerI) { + defer space.GetSpace(c.Info.MapID).User.Range(func(playerID uint32, v common.PlayerI) bool { data.Head.Result = 0 result = &user.ChangeDoodleOutboundInfo{ UserId: c.Info.UserID, @@ -104,6 +106,7 @@ func (h Controller) ChangePlayerDoodle(data *user.ChangeDoodleInboundInfo, c *pl Texture: c.Info.Texture, } v.SendPack(data.Head.Pack(result)) + return false }) return nil, -1 diff --git a/logic/go.mod b/logic/go.mod index 18207b908..5619b347e 100644 --- a/logic/go.mod +++ b/logic/go.mod @@ -39,6 +39,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mhmtszr/concurrent-swiss-map v1.0.9 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/redis/go-redis/v9 v9.5.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect diff --git a/logic/go.sum b/logic/go.sum index a014813fe..a8c26a5a5 100644 --- a/logic/go.sum +++ b/logic/go.sum @@ -22,6 +22,7 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/creasty/defaults v1.8.0 h1:z27FJxCAa0JKt3utc0sCImAEb+spPucmKoOdLHvHYKk= github.com/creasty/defaults v1.8.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= @@ -69,6 +70,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mhmtszr/concurrent-swiss-map v1.0.9 h1:ijAlVG/QHC4A4FRdfdtq0oRJ03Zx9dsF8RSiBQB/gKk= +github.com/mhmtszr/concurrent-swiss-map v1.0.9/go.mod h1:F6QETL48Qn7jEJ3ZPt7EqRZjAAZu7lRQeQGIzXuUIDc= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/panjf2000/ants/v2 v2.11.3 h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg= @@ -77,6 +80,7 @@ github.com/panjf2000/gnet/v2 v2.9.1 h1:bKewICy/0xnQ9PMzNaswpe/Ah14w1TrRk91LHTcbI github.com/panjf2000/gnet/v2 v2.9.1/go.mod h1:WQTxDWYuQ/hz3eccH0FN32IVuvZ19HewEWx0l62fx7E= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pointernil/bitset32 v0.0.1 h1:GL7o6ehG4W5ztXic75ncAmKzSxYQRSKxyaz2wOdz2aM= github.com/pointernil/bitset32 v0.0.1/go.mod h1:naghmAYTkvJhKSCVPbBwLAXkHMF2WBIJ1bJpnFpmQwI= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= diff --git a/logic/service/fight/cmd.go b/logic/service/fight/cmd.go index c761f6807..c5003fb0f 100644 --- a/logic/service/fight/cmd.go +++ b/logic/service/fight/cmd.go @@ -35,6 +35,13 @@ type StartPetWarInboundInfo struct { Head player.TomeeHeader `cmd:"2431" struc:"[0]pad"` } +// 表示"宠物王加入"的入站消息数据 +type PetKingJoinInboundInfo struct { + Head player.TomeeHeader `cmd:"2413" struc:"[0]pad"` + Type uint32 // 战斗类型:5=单精灵,6=多精灵,11=精灵大师赛 (对应Java的@UInt long type) + FightType uint32 // 仅当Type为11时有效 (对应Java的@UInt long fightType) +} + // HandleFightInviteInboundInfo 处理战斗邀请的入站消息 type HandleFightInviteInboundInfo struct { diff --git a/logic/service/fight/effect/EffectAttackMiss.go b/logic/service/fight/effect/EffectAttackMiss.go index 2a2a08a16..5a6f88d58 100644 --- a/logic/service/fight/effect/EffectAttackMiss.go +++ b/logic/service/fight/effect/EffectAttackMiss.go @@ -67,5 +67,5 @@ func (e *EffectAttackMiss) Skill_Hit_ex() bool { // 设置参数:复用父类逻辑,设置持续回合 func (e *EffectAttackMiss) SetArgs(t *input.Input, a ...int) { e.EffectNode.SetArgs(t, a...) - e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0]) // 持续回合由SideEffectArgs[0]指定 + e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0] - 1) // 持续回合由SideEffectArgs[0]指定 } diff --git a/logic/service/fight/effect/EffectPhysicalAttackAddStatus.go b/logic/service/fight/effect/EffectPhysicalAttackAddStatus.go index 5792a3629..6682efdc4 100644 --- a/logic/service/fight/effect/EffectPhysicalAttackAddStatus.go +++ b/logic/service/fight/effect/EffectPhysicalAttackAddStatus.go @@ -88,10 +88,7 @@ func (e *EffectPhysicalAttackAddStatus) SetArgs(t *input.Input, a ...int) { // 计算持续回合(封装为独立方法,增强可读性) func (e *EffectPhysicalAttackAddStatus) getDuration() int { - // 优先使用配置的回合数(SideEffectArgs[1]) - if len(e.EffectNode.SideEffectArgs) > 1 { - return e.EffectNode.SideEffectArgs[1] - } + // 默认随机2~3回合(Int31n(2)返回0/1,+2后为2/3) return int(e.Input.FightC.GetRand().Int31n(2)) + 2 } diff --git a/logic/service/maps/mapin.go b/logic/service/maps/mapin.go index b73d22214..7924335cb 100644 --- a/logic/service/maps/mapin.go +++ b/logic/service/maps/mapin.go @@ -1,6 +1,7 @@ package maps import ( + "blazing/logic/service/common" "blazing/logic/service/player" "blazing/logic/service/space" @@ -24,11 +25,14 @@ type InInfo struct { func (t *InInfo) Broadcast(mapid uint32, o OutInfo) { - for _, v := range space.GetSpace(mapid).User.Items() { + space.GetSpace(mapid).User.Range(func(k uint32, v common.PlayerI) (stop bool) { + t.Head.Result = 0 v.SendPack(t.Head.Pack(&o)) - } + return false + }) + } // 这里存储星球的map diff --git a/logic/service/maps/mapout.go b/logic/service/maps/mapout.go index a4183d051..d37354b13 100644 --- a/logic/service/maps/mapout.go +++ b/logic/service/maps/mapout.go @@ -11,10 +11,11 @@ type LeaveMapInboundInfo struct { } func (t *LeaveMapInboundInfo) Broadcast(mapid uint32, o space.LeaveMapOutboundInfo) { - space.GetSpace(mapid).User.IterCb(func(playerID uint32, player common.PlayerI) { + space.GetSpace(mapid).User.Range(func(playerID uint32, player common.PlayerI) bool { t.Head.Result = 0 player.SendPack(t.Head.Pack(&o)) + return false }) } diff --git a/logic/service/maps/walk.go b/logic/service/maps/walk.go index 4fa0c41bf..78c4c3589 100644 --- a/logic/service/maps/walk.go +++ b/logic/service/maps/walk.go @@ -30,10 +30,11 @@ func (t *WalkInInfo) Broadcast(mapid uint32, o WalkOutInfo) { if !limiter.Allow() { return } - space.GetSpace(mapid).User.IterCb(func(playerID uint32, player common.PlayerI) { + space.GetSpace(mapid).User.Range(func(playerID uint32, player common.PlayerI) bool { t.Head.Result = 0 tt := t.Head.Pack(&o) player.SendPack(tt) + return false }) } diff --git a/logic/service/pet/pet.go b/logic/service/pet/pet.go index 408e6369f..3b8c7e933 100644 --- a/logic/service/pet/pet.go +++ b/logic/service/pet/pet.go @@ -1,6 +1,7 @@ package pet import ( + "blazing/logic/service/common" "blazing/logic/service/player" "blazing/logic/service/space" "blazing/modules/blazing/model" @@ -39,12 +40,13 @@ type PetShowInboundInfo struct { } func (t *PetShowInboundInfo) Broadcast(mapid uint32, o PetShowOutboundInfo) { - - for _, v := range space.GetSpace(mapid).User.Items() { + space.GetSpace(mapid).User.Range(func(key uint32, v common.PlayerI) (stop bool) { t.Head.Result = 0 v.SendPack(t.Head.Pack(&o)) - } + return false + }) + } type PetShowOutboundInfo struct { diff --git a/logic/service/player/fight.go b/logic/service/player/fight.go index ffaa95d57..ae8c67b50 100644 --- a/logic/service/player/fight.go +++ b/logic/service/player/fight.go @@ -11,7 +11,7 @@ import ( func (lw *Player) InvitePlayerToBattle() { pinfo := lw.PVPinfo - space.GetSpace(lw.Info.MapID).User.IterCb(func(key uint32, v common.PlayerI) { + space.GetSpace(lw.Info.MapID).User.Range(func(key uint32, v common.PlayerI) bool { value := v.(*Player) if key == uint32(pinfo.PlayerID) { //说明这里是针对玩家邀请的 @@ -24,30 +24,31 @@ func (lw *Player) InvitePlayerToBattle() { Mode: pinfo.Mode, } value.SendPack(t1.Pack(&t)) - return + return true } - + return false }) } -func (p *Player) PET_MELEE() *Player { +func (p *Player) Pet_joinFight() *Player { var lw *Player //pinfo := lw.PVPinfo - space.GetSpace(p.Info.MapID).User.IterCb(func(key uint32, v common.PlayerI) { + space.GetSpace(p.Info.MapID).User.Range(func(key uint32, v common.PlayerI) bool { value := v.(*Player) if value.PVPinfo != nil && value != p { //确认是乱斗模式 - if value.PVPinfo.Mode == info.BattleMode.PET_MELEE { - lw.PVPinfo = nil //先将自身的准备信息置空 + if *value.PVPinfo == *p.PVPinfo { + p.PVPinfo = nil //先将自身的准备信息置空 + value.PVPinfo = nil lw = value - return + return true } } - + return false }) return lw } diff --git a/logic/service/player/player.go b/logic/service/player/player.go index 9eec80840..17c065a2f 100644 --- a/logic/service/player/player.go +++ b/logic/service/player/player.go @@ -311,11 +311,13 @@ func LeaveMap(c common.PlayerI) { } t := NewTomeeHeader(2002, c.GetInfo().UserID) - for k, v := range space.GetSpace(c.GetInfo().MapID).User.Items() { + space.GetSpace(c.GetInfo().MapID).User.Range(func(k uint32, v common.PlayerI) (stop bool) { + if k != c.GetInfo().UserID { v.SendPack(t.Pack(&space.LeaveMapOutboundInfo{UserID: c.GetInfo().UserID})) } + return false + }) - } - space.GetSpace(c.GetInfo().MapID).User.Remove(c.GetInfo().UserID) + space.GetSpace(c.GetInfo().MapID).User.Delete(c.GetInfo().UserID) } diff --git a/logic/service/space/space.go b/logic/service/space/space.go index 347227929..fe5aa20a1 100644 --- a/logic/service/space/space.go +++ b/logic/service/space/space.go @@ -3,14 +3,15 @@ package space import ( "blazing/common/data/xmlres" "blazing/common/utils" - "blazing/logic/service/common" + + csmap "github.com/mhmtszr/concurrent-swiss-map" ) // Space 针对Player的并发安全map,键为uint32类型 type Space struct { - User utils.ConcurrentMap[uint32, common.PlayerI] // 存储玩家数据的map,键为玩家ID - CanRefresh bool //是否能够刷怪 + User *csmap.CsMap[uint32, common.PlayerI] // 存储玩家数据的map,键为玩家ID + CanRefresh bool //是否能够刷怪 //ID uint32 // 地图ID Name string //地图名称 // DefaultPos model.Pos //默认位置DefaultPos @@ -21,9 +22,20 @@ type Space struct { // NewSyncMap 创建一个新的玩家同步map func NewSpace() *Space { return &Space{ - User: utils.NewWithCustomShardingFunction[uint32, common.PlayerI](func(key uint32) uint32 { - return key - }), + User: csmap.New[uint32, common.PlayerI]( + // set the number of map shards. the default value is 32. + csmap.WithShardCount[uint32, common.PlayerI](32), + + // // if don't set custom hasher, use the built-in maphash. + // csmap.WithCustomHasher[string, int](func(key string) uint64 { + // hash := fnv.New64a() + // hash.Write([]byte(key)) + // return hash.Sum64() + // }), + + // set the total capacity, every shard map has total capacity/shard count capacity. the default value is 0. + // csmap.WithSize[string, int](1000), + ), } }