```
feat(space): 替换并发安全map实现以提升性能 将原来基于`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引入新的依赖库。 ```
This commit is contained in:
@@ -281,7 +281,7 @@ func (m ConcurrentMap[K, V]) Items() map[K]V {
|
|||||||
// maps. RLock is held for all calls for a given shard
|
// maps. RLock is held for all calls for a given shard
|
||||||
// therefore callback sess consistent view of a shard,
|
// therefore callback sess consistent view of a shard,
|
||||||
// but not across the shards
|
// 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
|
// Callback based iterator, cheapest way to read
|
||||||
// all elements in a map.
|
// all elements in a map.
|
||||||
@@ -290,7 +290,10 @@ func (m ConcurrentMap[K, V]) IterCb(fn IterCb[K, V]) {
|
|||||||
shard := (m.shards)[idx]
|
shard := (m.shards)[idx]
|
||||||
shard.RLock()
|
shard.RLock()
|
||||||
for key, value := range shard.items {
|
for key, value := range shard.items {
|
||||||
fn(key, value)
|
|
||||||
|
if !fn(key, value) {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
shard.RUnlock()
|
shard.RUnlock()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ func (h *Controller) ChangePlayerName(data *user.ChangePlayerNameInboundInfo, c
|
|||||||
UserID: c.Info.UserID,
|
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))
|
player.SendPack(data.Head.Pack(&result))
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return result, 0
|
return result, 0
|
||||||
|
|||||||
@@ -17,9 +17,37 @@ func (h Controller) PET_MELEE(data *fight.StartPetWarInboundInfo, c *player.Play
|
|||||||
c.PVPinfo = &info.PVPinfo{
|
c.PVPinfo = &info.PVPinfo{
|
||||||
Mode: info.BattleMode.PET_MELEE,
|
Mode: info.BattleMode.PET_MELEE,
|
||||||
Status: info.BattleStatus.FIGHT_WITH_PLAYER}
|
Status: info.BattleStatus.FIGHT_WITH_PLAYER}
|
||||||
g := c.PET_MELEE()
|
g := c.Pet_joinFight()
|
||||||
if g != nil {
|
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
|
return
|
||||||
|
|||||||
@@ -76,10 +76,11 @@ func (h Controller) ChangePlayerCloth(data *item.ChangePlayerClothInboundInfo, c
|
|||||||
result.ClothList = append(result.ClothList, model.PeopleItemInfo{ID: v, Level: 1})
|
result.ClothList = append(result.ClothList, model.PeopleItemInfo{ID: v, Level: 1})
|
||||||
}
|
}
|
||||||
c.Info.Clothes = result.ClothList
|
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))
|
// fmt.Println("ChangePlayerCloth", playerID, data.Head.Pack(result))
|
||||||
data.Head.Result = 0
|
data.Head.Result = 0
|
||||||
player.SendPack(data.Head.Pack(result))
|
player.SendPack(data.Head.Pack(result))
|
||||||
|
return false
|
||||||
|
|
||||||
})
|
})
|
||||||
return nil, -1
|
return nil, -1
|
||||||
|
|||||||
@@ -106,11 +106,11 @@ func (h *Controller) Login(data *user.MAIN_LOGIN_IN, c gnet.Conn) (result *user.
|
|||||||
//copier.Copy(t.Info, tt)
|
//copier.Copy(t.Info, tt)
|
||||||
t1 := player.NewTomeeHeader(2001, t.Info.UserID)
|
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))
|
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
|
return result, 0
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import (
|
|||||||
|
|
||||||
func (h *Controller) MapEnter(data *maps.InInfo, c *player.Player) (result *maps.OutInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
func (h *Controller) MapEnter(data *maps.InInfo, c *player.Player) (result *maps.OutInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||||
|
|
||||||
c.Info.MapID = data.MapId //登录地图
|
c.Info.MapID = data.MapId //登录地图
|
||||||
space.GetSpace(c.Info.MapID).User.Set(c.Info.UserID, c) //添加玩家
|
space.GetSpace(c.Info.MapID).User.Store(c.Info.UserID, c) //添加玩家
|
||||||
|
|
||||||
result = maps.NewOutInfo()
|
result = maps.NewOutInfo()
|
||||||
c.Info.Pos = data.Point
|
c.Info.Pos = data.Point
|
||||||
@@ -39,7 +39,7 @@ func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player)
|
|||||||
c.Canmon = false
|
c.Canmon = false
|
||||||
c.Changemap = true //可以刷怪
|
c.Changemap = true //可以刷怪
|
||||||
data.Broadcast(c.Info.MapID, space.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播
|
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 // 重置当前地图
|
c.Info.MapID = 0 // 重置当前地图
|
||||||
@@ -49,11 +49,12 @@ func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *player.Play
|
|||||||
|
|
||||||
result = &maps.ListMapPlayerOutboundInfo{}
|
result = &maps.ListMapPlayerOutboundInfo{}
|
||||||
result.Player = make([]maps.OutInfo, 0)
|
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()
|
result1 := maps.NewOutInfo()
|
||||||
copier.CopyWithOption(result1, player.GetInfo(), copier.Option{DeepCopy: true})
|
copier.CopyWithOption(result1, player.GetInfo(), copier.Option{DeepCopy: true})
|
||||||
result.Player = append(result.Player, *result1)
|
result.Player = append(result.Player, *result1)
|
||||||
result.Player = LastFourElements(result.Player)
|
result.Player = LastFourElements(result.Player)
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
c.Canmon = true //可以刷怪
|
c.Canmon = true //可以刷怪
|
||||||
|
|||||||
@@ -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) {
|
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{
|
ret := &user.AimatOutboundInfo{
|
||||||
|
|
||||||
ItemId: data.ItemId,
|
ItemId: data.ItemId,
|
||||||
@@ -47,14 +47,14 @@ func (h Controller) Aimat(data *user.AimatInboundInfo, c *player.Player) (result
|
|||||||
}
|
}
|
||||||
data.Head.Result = 0
|
data.Head.Result = 0
|
||||||
player.SendPack(data.Head.Pack(ret))
|
player.SendPack(data.Head.Pack(ret))
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil, -1
|
return nil, -1
|
||||||
}
|
}
|
||||||
func (h Controller) Chat(data *user.ChatInboundInfo, c *player.Player) (result *user.ChatOutboundInfo, err errorcode.ErrorCode) {
|
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{
|
result = &user.ChatOutboundInfo{
|
||||||
|
|
||||||
Message: string([]byte(data.Message)[:data.MessageLen-1]),
|
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, '*')
|
result.Message = cool.Filter.Replace(result.Message, '*')
|
||||||
data.Head.Result = 0
|
data.Head.Result = 0
|
||||||
v.SendPack(data.Head.Pack(result))
|
v.SendPack(data.Head.Pack(result))
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil, -1
|
return nil, -1
|
||||||
@@ -76,7 +77,7 @@ func (h Controller) ChangePlayerColor(data *user.ChangeColorInboundInfo, c *play
|
|||||||
c.Info.Color = data.Color
|
c.Info.Color = data.Color
|
||||||
c.Info.Texture = 0
|
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
|
data.Head.Result = 0
|
||||||
result = &user.ChangeColorOutboundInfo{
|
result = &user.ChangeColorOutboundInfo{
|
||||||
UserId: c.Info.UserID,
|
UserId: c.Info.UserID,
|
||||||
@@ -85,6 +86,7 @@ func (h Controller) ChangePlayerColor(data *user.ChangeColorInboundInfo, c *play
|
|||||||
Texture: c.Info.Texture,
|
Texture: c.Info.Texture,
|
||||||
}
|
}
|
||||||
v.SendPack(data.Head.Pack(result))
|
v.SendPack(data.Head.Pack(result))
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil, -1
|
return nil, -1
|
||||||
@@ -95,7 +97,7 @@ func (h Controller) ChangePlayerDoodle(data *user.ChangeDoodleInboundInfo, c *pl
|
|||||||
}
|
}
|
||||||
c.Info.Texture = data.Id
|
c.Info.Texture = data.Id
|
||||||
c.Info.Color = data.Color
|
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
|
data.Head.Result = 0
|
||||||
result = &user.ChangeDoodleOutboundInfo{
|
result = &user.ChangeDoodleOutboundInfo{
|
||||||
UserId: c.Info.UserID,
|
UserId: c.Info.UserID,
|
||||||
@@ -104,6 +106,7 @@ func (h Controller) ChangePlayerDoodle(data *user.ChangeDoodleInboundInfo, c *pl
|
|||||||
Texture: c.Info.Texture,
|
Texture: c.Info.Texture,
|
||||||
}
|
}
|
||||||
v.SendPack(data.Head.Pack(result))
|
v.SendPack(data.Head.Pack(result))
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil, -1
|
return nil, -1
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ require (
|
|||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // 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/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.5.1 // indirect
|
github.com/redis/go-redis/v9 v9.5.1 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
|||||||
@@ -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 h1:z27FJxCAa0JKt3utc0sCImAEb+spPucmKoOdLHvHYKk=
|
||||||
github.com/creasty/defaults v1.8.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM=
|
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 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 h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
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=
|
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.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 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
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 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||||
github.com/panjf2000/ants/v2 v2.11.3 h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg=
|
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/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/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 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 h1:GL7o6ehG4W5ztXic75ncAmKzSxYQRSKxyaz2wOdz2aM=
|
||||||
github.com/pointernil/bitset32 v0.0.1/go.mod h1:naghmAYTkvJhKSCVPbBwLAXkHMF2WBIJ1bJpnFpmQwI=
|
github.com/pointernil/bitset32 v0.0.1/go.mod h1:naghmAYTkvJhKSCVPbBwLAXkHMF2WBIJ1bJpnFpmQwI=
|
||||||
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
|
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
|
||||||
|
|||||||
@@ -35,6 +35,13 @@ type StartPetWarInboundInfo struct {
|
|||||||
Head player.TomeeHeader `cmd:"2431" struc:"[0]pad"`
|
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 处理战斗邀请的入站消息
|
// HandleFightInviteInboundInfo 处理战斗邀请的入站消息
|
||||||
|
|
||||||
type HandleFightInviteInboundInfo struct {
|
type HandleFightInviteInboundInfo struct {
|
||||||
|
|||||||
@@ -67,5 +67,5 @@ func (e *EffectAttackMiss) Skill_Hit_ex() bool {
|
|||||||
// 设置参数:复用父类逻辑,设置持续回合
|
// 设置参数:复用父类逻辑,设置持续回合
|
||||||
func (e *EffectAttackMiss) SetArgs(t *input.Input, a ...int) {
|
func (e *EffectAttackMiss) SetArgs(t *input.Input, a ...int) {
|
||||||
e.EffectNode.SetArgs(t, a...)
|
e.EffectNode.SetArgs(t, a...)
|
||||||
e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0]) // 持续回合由SideEffectArgs[0]指定
|
e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0] - 1) // 持续回合由SideEffectArgs[0]指定
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,10 +88,7 @@ func (e *EffectPhysicalAttackAddStatus) SetArgs(t *input.Input, a ...int) {
|
|||||||
|
|
||||||
// 计算持续回合(封装为独立方法,增强可读性)
|
// 计算持续回合(封装为独立方法,增强可读性)
|
||||||
func (e *EffectPhysicalAttackAddStatus) getDuration() 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)
|
// 默认随机2~3回合(Int31n(2)返回0/1,+2后为2/3)
|
||||||
return int(e.Input.FightC.GetRand().Int31n(2)) + 2
|
return int(e.Input.FightC.GetRand().Int31n(2)) + 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package maps
|
package maps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"blazing/logic/service/common"
|
||||||
"blazing/logic/service/player"
|
"blazing/logic/service/player"
|
||||||
"blazing/logic/service/space"
|
"blazing/logic/service/space"
|
||||||
|
|
||||||
@@ -24,11 +25,14 @@ type InInfo struct {
|
|||||||
|
|
||||||
func (t *InInfo) Broadcast(mapid uint32, o OutInfo) {
|
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
|
t.Head.Result = 0
|
||||||
|
|
||||||
v.SendPack(t.Head.Pack(&o))
|
v.SendPack(t.Head.Pack(&o))
|
||||||
}
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 这里存储星球的map
|
// 这里存储星球的map
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ type LeaveMapInboundInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *LeaveMapInboundInfo) Broadcast(mapid uint32, o space.LeaveMapOutboundInfo) {
|
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
|
t.Head.Result = 0
|
||||||
|
|
||||||
player.SendPack(t.Head.Pack(&o))
|
player.SendPack(t.Head.Pack(&o))
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,11 @@ func (t *WalkInInfo) Broadcast(mapid uint32, o WalkOutInfo) {
|
|||||||
if !limiter.Allow() {
|
if !limiter.Allow() {
|
||||||
return
|
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
|
t.Head.Result = 0
|
||||||
tt := t.Head.Pack(&o)
|
tt := t.Head.Pack(&o)
|
||||||
player.SendPack(tt)
|
player.SendPack(tt)
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package pet
|
package pet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"blazing/logic/service/common"
|
||||||
"blazing/logic/service/player"
|
"blazing/logic/service/player"
|
||||||
"blazing/logic/service/space"
|
"blazing/logic/service/space"
|
||||||
"blazing/modules/blazing/model"
|
"blazing/modules/blazing/model"
|
||||||
@@ -39,12 +40,13 @@ type PetShowInboundInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *PetShowInboundInfo) Broadcast(mapid uint32, o PetShowOutboundInfo) {
|
func (t *PetShowInboundInfo) Broadcast(mapid uint32, o PetShowOutboundInfo) {
|
||||||
|
space.GetSpace(mapid).User.Range(func(key uint32, v common.PlayerI) (stop bool) {
|
||||||
for _, v := range space.GetSpace(mapid).User.Items() {
|
|
||||||
t.Head.Result = 0
|
t.Head.Result = 0
|
||||||
|
|
||||||
v.SendPack(t.Head.Pack(&o))
|
v.SendPack(t.Head.Pack(&o))
|
||||||
}
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PetShowOutboundInfo struct {
|
type PetShowOutboundInfo struct {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
func (lw *Player) InvitePlayerToBattle() {
|
func (lw *Player) InvitePlayerToBattle() {
|
||||||
|
|
||||||
pinfo := lw.PVPinfo
|
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)
|
value := v.(*Player)
|
||||||
if key == uint32(pinfo.PlayerID) { //说明这里是针对玩家邀请的
|
if key == uint32(pinfo.PlayerID) { //说明这里是针对玩家邀请的
|
||||||
@@ -24,30 +24,31 @@ func (lw *Player) InvitePlayerToBattle() {
|
|||||||
Mode: pinfo.Mode,
|
Mode: pinfo.Mode,
|
||||||
}
|
}
|
||||||
value.SendPack(t1.Pack(&t))
|
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
|
var lw *Player
|
||||||
//pinfo := lw.PVPinfo
|
//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)
|
value := v.(*Player)
|
||||||
|
|
||||||
if value.PVPinfo != nil && value != p {
|
if value.PVPinfo != nil && value != p {
|
||||||
//确认是乱斗模式
|
//确认是乱斗模式
|
||||||
|
|
||||||
if value.PVPinfo.Mode == info.BattleMode.PET_MELEE {
|
if *value.PVPinfo == *p.PVPinfo {
|
||||||
lw.PVPinfo = nil //先将自身的准备信息置空
|
p.PVPinfo = nil //先将自身的准备信息置空
|
||||||
|
value.PVPinfo = nil
|
||||||
lw = value
|
lw = value
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
return lw
|
return lw
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -311,11 +311,13 @@ func LeaveMap(c common.PlayerI) {
|
|||||||
}
|
}
|
||||||
t := NewTomeeHeader(2002, c.GetInfo().UserID)
|
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 {
|
if k != c.GetInfo().UserID {
|
||||||
v.SendPack(t.Pack(&space.LeaveMapOutboundInfo{UserID: c.GetInfo().UserID}))
|
v.SendPack(t.Pack(&space.LeaveMapOutboundInfo{UserID: c.GetInfo().UserID}))
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
}
|
space.GetSpace(c.GetInfo().MapID).User.Delete(c.GetInfo().UserID)
|
||||||
space.GetSpace(c.GetInfo().MapID).User.Remove(c.GetInfo().UserID)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,15 @@ package space
|
|||||||
import (
|
import (
|
||||||
"blazing/common/data/xmlres"
|
"blazing/common/data/xmlres"
|
||||||
"blazing/common/utils"
|
"blazing/common/utils"
|
||||||
|
|
||||||
"blazing/logic/service/common"
|
"blazing/logic/service/common"
|
||||||
|
|
||||||
|
csmap "github.com/mhmtszr/concurrent-swiss-map"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Space 针对Player的并发安全map,键为uint32类型
|
// Space 针对Player的并发安全map,键为uint32类型
|
||||||
type Space struct {
|
type Space struct {
|
||||||
User utils.ConcurrentMap[uint32, common.PlayerI] // 存储玩家数据的map,键为玩家ID
|
User *csmap.CsMap[uint32, common.PlayerI] // 存储玩家数据的map,键为玩家ID
|
||||||
CanRefresh bool //是否能够刷怪
|
CanRefresh bool //是否能够刷怪
|
||||||
//ID uint32 // 地图ID
|
//ID uint32 // 地图ID
|
||||||
Name string //地图名称
|
Name string //地图名称
|
||||||
// DefaultPos model.Pos //默认位置DefaultPos
|
// DefaultPos model.Pos //默认位置DefaultPos
|
||||||
@@ -21,9 +22,20 @@ type Space struct {
|
|||||||
// NewSyncMap 创建一个新的玩家同步map
|
// NewSyncMap 创建一个新的玩家同步map
|
||||||
func NewSpace() *Space {
|
func NewSpace() *Space {
|
||||||
return &Space{
|
return &Space{
|
||||||
User: utils.NewWithCustomShardingFunction[uint32, common.PlayerI](func(key uint32) uint32 {
|
User: csmap.New[uint32, common.PlayerI](
|
||||||
return key
|
// 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),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user