Merge branch 'main' of https://github.com/72wo/blazing
This commit is contained in:
@@ -3,6 +3,8 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"blazing/common/data/xmlres"
|
"blazing/common/data/xmlres"
|
||||||
"blazing/common/socket/errorcode"
|
"blazing/common/socket/errorcode"
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"blazing/logic/service/fight"
|
"blazing/logic/service/fight"
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
@@ -13,13 +15,41 @@ import (
|
|||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func processMonID(bm string) string {
|
||||||
|
// 按空格分割字符串
|
||||||
|
monid := strings.Split(bm, " ")
|
||||||
|
|
||||||
|
// 过滤分割后可能的空字符串(如连续空格导致的空元素)
|
||||||
|
filtered := make([]string, 0, len(monid))
|
||||||
|
for _, m := range monid {
|
||||||
|
if m != "" {
|
||||||
|
filtered = append(filtered, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
monid = filtered
|
||||||
|
|
||||||
|
var selected string
|
||||||
|
switch len(monid) {
|
||||||
|
case 0:
|
||||||
|
// 无元素时,可返回空或默认值(根据业务需求调整)
|
||||||
|
selected = ""
|
||||||
|
case 1:
|
||||||
|
// 长度为1时,取第一个(唯一的元素)
|
||||||
|
selected = monid[0]
|
||||||
|
default:
|
||||||
|
// 长度大于1时,随机选取一个
|
||||||
|
randomIdx := rand.Intn(len(monid))
|
||||||
|
selected = monid[randomIdx]
|
||||||
|
}
|
||||||
|
return selected
|
||||||
|
}
|
||||||
|
|
||||||
// 挑战地图boss
|
// 挑战地图boss
|
||||||
func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||||
if !c.CanFight() {
|
if !c.CanFight() {
|
||||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||||
}
|
}
|
||||||
|
|
||||||
var petid int
|
|
||||||
var mo *model.PetInfo
|
var mo *model.PetInfo
|
||||||
moinfo := &model.PlayerInfo{}
|
moinfo := &model.PlayerInfo{}
|
||||||
// 新手任务2(选择不同精灵)
|
// 新手任务2(选择不同精灵)
|
||||||
@@ -34,28 +64,6 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
|
|||||||
// </Boss>
|
// </Boss>
|
||||||
// </Bosses>
|
// </Bosses>
|
||||||
// </Map>
|
// </Map>
|
||||||
if c.Info.MapID == 515 && data.BossId == 0 { //说明是新手,随机生成
|
|
||||||
switch c.Info.PetList[0].ID {
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
petid = 4
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
petid = 1
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
petid = 7
|
|
||||||
}
|
|
||||||
|
|
||||||
mo = c.GenPetInfo(
|
|
||||||
int(petid), 24, //24个体
|
|
||||||
-1,
|
|
||||||
0, //野怪没特性
|
|
||||||
0,
|
|
||||||
50)
|
|
||||||
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
|
|
||||||
moinfo.PetList = append(moinfo.PetList, *mo)
|
|
||||||
} else {
|
|
||||||
|
|
||||||
mdata, ok := xmlres.MonsterMap[int(c.Info.MapID)]
|
mdata, ok := xmlres.MonsterMap[int(c.Info.MapID)]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -65,14 +73,12 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
|
|||||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||||
}
|
}
|
||||||
for _, bc := range mdata.Bosses {
|
for _, bc := range mdata.Bosses {
|
||||||
if bc.Id == nil {
|
if (bc.Id == nil && data.BossId == 0) || uint32(*bc.Id) == data.BossId { //打默认第一个boss
|
||||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
|
||||||
|
|
||||||
}
|
|
||||||
if uint32(*bc.Id) == data.BossId {
|
|
||||||
for _, bm := range bc.BossMon {
|
for _, bm := range bc.BossMon {
|
||||||
|
|
||||||
mo = c.GenPetInfo(
|
mo = c.GenPetInfo(
|
||||||
gconv.Int(bm.MonID), 24, //24个体
|
gconv.Int(processMonID(bm.MonID)), 24, //24个体
|
||||||
-1,
|
-1,
|
||||||
0, //野怪没特性
|
0, //野怪没特性
|
||||||
0,
|
0,
|
||||||
@@ -91,8 +97,6 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ai := player.NewAI_player(moinfo)
|
ai := player.NewAI_player(moinfo)
|
||||||
fight.NewFight(info.BattleMode.MULTI_MODE, info.BattleStatus.FIGHT_WITH_BOSS, c, ai, func(foi *info.FightOverInfo) {
|
fight.NewFight(info.BattleMode.MULTI_MODE, info.BattleStatus.FIGHT_WITH_BOSS, c, ai, func(foi *info.FightOverInfo) {
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"blazing/common/socket/errorcode"
|
"blazing/common/socket/errorcode"
|
||||||
|
|
||||||
"blazing/logic/service/common"
|
|
||||||
"blazing/logic/service/maphot"
|
"blazing/logic/service/maphot"
|
||||||
"blazing/logic/service/maps"
|
"blazing/logic/service/maps"
|
||||||
"blazing/logic/service/maps/info"
|
"blazing/logic/service/maps/info"
|
||||||
@@ -11,19 +10,24 @@ import (
|
|||||||
"blazing/logic/service/space"
|
"blazing/logic/service/space"
|
||||||
|
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/panjf2000/ants/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var mappool, _ = ants.NewPool(-1)
|
||||||
|
|
||||||
func (h *Controller) MapEnter(data *maps.InInfo, c *player.Player) (result *info.OutInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
func (h *Controller) MapEnter(data *maps.InInfo, c *player.Player) (result *info.OutInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||||
|
|
||||||
c.Info.MapID = data.MapId //登录地图
|
c.Info.MapID = data.MapId //登录地图
|
||||||
space.GetSpace(c.Info.MapID).User.Store(c.Info.UserID, c) //添加玩家
|
c.GetSpace().User.Store(c.Info.UserID, c) //添加玩家
|
||||||
|
|
||||||
result = info.NewOutInfo()
|
result = info.NewOutInfo()
|
||||||
c.Info.Pos = data.Point
|
c.Info.Pos = data.Point
|
||||||
copier.Copy(result, c.Info)
|
copier.Copy(result, c.Info)
|
||||||
|
mappool.Submit(func() {
|
||||||
|
c.GetSpace().EnterMap(c)
|
||||||
|
})
|
||||||
|
|
||||||
go space.GetSpace(c.Info.MapID).EnterMap(c) //玩家进入地图
|
return result, 0
|
||||||
return result, -1
|
|
||||||
}
|
}
|
||||||
func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *maphot.OutInfo, err errorcode.ErrorCode) {
|
func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *maphot.OutInfo, err errorcode.ErrorCode) {
|
||||||
|
|
||||||
@@ -39,33 +43,21 @@ 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, info.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播
|
//data.Broadcast(c.Info.MapID, info.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播
|
||||||
go space.GetSpace(c.Info.MapID).LeaveMap(c) //玩家离开地图
|
mappool.Submit(func() {
|
||||||
|
c.GetSpace().LeaveMap(c) //玩家离开地图
|
||||||
|
})
|
||||||
|
|
||||||
// 如果有正在运行的刷怪协程,发送停止信号
|
// 如果有正在运行的刷怪协程,发送停止信号
|
||||||
|
|
||||||
c.Info.MapID = 0 // 重置当前地图
|
//c.Info.MapID = 0 // 重置当前地图
|
||||||
return &info.LeaveMapOutboundInfo{UserID: c.Info.UserID}, -1
|
return &info.LeaveMapOutboundInfo{UserID: c.Info.UserID}, 0
|
||||||
}
|
}
|
||||||
func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *player.Player) (result *maps.ListMapPlayerOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *player.Player) (result *info.ListMapPlayerOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||||
|
|
||||||
result = &maps.ListMapPlayerOutboundInfo{}
|
result = &info.ListMapPlayerOutboundInfo{
|
||||||
result.Player = make([]info.OutInfo, 0)
|
Player: c.GetSpace().GetInfo(),
|
||||||
space.GetSpace(c.Info.MapID).User.Range(func(playerID uint32, player common.PlayerI) bool {
|
}
|
||||||
result1 := info.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 //可以刷怪
|
c.Canmon = true //可以刷怪
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func LastFourElements[T any](s []T) []T {
|
|
||||||
n := len(s)
|
|
||||||
if n <= 30 {
|
|
||||||
// 切片长度小于等于4时,返回整个切片
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
// 切片长度大于4时,返回最后4个元素(从n-4索引到末尾)
|
|
||||||
return s[n-30:]
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ func (h Controller) Complete_Task(data *task.CompleteTaskInboundInfo, c *player.
|
|||||||
//task.Tasktopic.Pub(*data)
|
//task.Tasktopic.Pub(*data)
|
||||||
|
|
||||||
tt := task.Get_Task_Info(*data)
|
tt := task.Get_Task_Info(*data)
|
||||||
|
if tt == nil {
|
||||||
|
return result, 0 //通过PUB/SUB回包
|
||||||
|
}
|
||||||
result.ItemList = tt.ItemList
|
result.ItemList = tt.ItemList
|
||||||
|
|
||||||
if tt.PetTypeId != 0 {
|
if tt.PetTypeId != 0 {
|
||||||
@@ -81,11 +84,12 @@ func (h Controller) Complete_Task(data *task.CompleteTaskInboundInfo, c *player.
|
|||||||
|
|
||||||
var ttt []model.SingleItemInfo
|
var ttt []model.SingleItemInfo
|
||||||
|
|
||||||
copier.Copy(ttt, result.ItemList)
|
copier.CopyWithOption(&ttt, &result.ItemList, copier.Option{IgnoreEmpty: true, DeepCopy: true})
|
||||||
|
ret := c.ItemAdd(ttt...) //获取成功的条目
|
||||||
|
result.ItemList = make([]task.ItemInfo, 0) //清空
|
||||||
|
copier.CopyWithOption(&result.ItemList, &ret, copier.Option{IgnoreEmpty: true, DeepCopy: true})
|
||||||
|
|
||||||
copier.Copy(result.ItemList, c.ItemAdd(ttt...))
|
return result, 0 //通过PUB/SUB回包
|
||||||
|
|
||||||
return result, -1 //通过PUB/SUB回包
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,22 +3,19 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"blazing/common/socket/errorcode"
|
"blazing/common/socket/errorcode"
|
||||||
"blazing/logic/service/maps"
|
"blazing/logic/service/maps"
|
||||||
|
"blazing/logic/service/maps/info"
|
||||||
"blazing/logic/service/player"
|
"blazing/logic/service/player"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h Controller) Walk(data *maps.WalkInInfo, c *player.Player) (result *maps.WalkOutInfo, err errorcode.ErrorCode) {
|
func (h Controller) Walk(data *maps.WalkInInfo, c *player.Player) (result *info.WalkOutInfo, err errorcode.ErrorCode) {
|
||||||
result = &maps.WalkOutInfo{
|
|
||||||
|
go c.GetSpace().Walk(info.WalkOutInfo{
|
||||||
Flag: data.Flag,
|
Flag: data.Flag,
|
||||||
Point: data.Point,
|
Point: data.Point,
|
||||||
Path: data.Path,
|
Path: data.Path,
|
||||||
}
|
UserID: c.Info.UserID,
|
||||||
|
})
|
||||||
|
|
||||||
result.UserID = data.Head.UserID
|
|
||||||
|
|
||||||
//glog.Debug(context.Background(), err1)
|
|
||||||
if !c.Info.Pos.BothLessThan50(data.Point) { //距离超过50才广播
|
|
||||||
data.Broadcast(c.Info.MapID, *result) //走路的广播
|
|
||||||
}
|
|
||||||
c.Info.Pos = data.Point
|
c.Info.Pos = data.Point
|
||||||
return nil, -1
|
return nil, -1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,4 +22,5 @@ type PlayerI interface {
|
|||||||
SetFightC(FightI)
|
SetFightC(FightI)
|
||||||
SendLeaveMapInfo(b maps.LeaveMapOutboundInfo)
|
SendLeaveMapInfo(b maps.LeaveMapOutboundInfo)
|
||||||
SendEnterMapInfo(b maps.OutInfo)
|
SendEnterMapInfo(b maps.OutInfo)
|
||||||
|
SendWalkMapInfo(b maps.WalkOutInfo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,28 @@ import (
|
|||||||
"github.com/creasty/defaults"
|
"github.com/creasty/defaults"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ListMapPlayerOutboundInfo struct {
|
||||||
|
PlayersLen uint32 `struc:"sizeof=Player" json:"player_len"`
|
||||||
|
|
||||||
|
// 穿戴装备的信息
|
||||||
|
Player []OutInfo ` json:"player"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeopleWalkOutboundInfo PeopleWalkOutboundInfo类,实现OutboundMessage接口
|
||||||
|
type WalkOutInfo struct {
|
||||||
|
// Flag: 0为走,1为飞行模式
|
||||||
|
Flag uint32 `fieldDesc:"0为走,1为飞行模式" codec:"uint"`
|
||||||
|
|
||||||
|
// UserID: 走动的人的米米号
|
||||||
|
UserID uint32 `fieldDesc:"走动的人的米米号" codec:"uint"`
|
||||||
|
|
||||||
|
// Point: 直接给坐标x,y
|
||||||
|
Point model.Pos `fieldDesc:"直接给坐标x,y"`
|
||||||
|
|
||||||
|
PathLen uint32 `struc:"sizeof=Path" `
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
// 这里存储星球的map
|
// 这里存储星球的map
|
||||||
//var planetmap utils.SyncMap[] //= space.NewSyncMap()
|
//var planetmap utils.SyncMap[] //= space.NewSyncMap()
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,9 @@
|
|||||||
package maps
|
package maps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/logic/service/maps/info"
|
|
||||||
"blazing/logic/service/player"
|
"blazing/logic/service/player"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ListMapPlayerInboundInfo struct {
|
type ListMapPlayerInboundInfo struct {
|
||||||
Head player.TomeeHeader `cmd:"2003" struc:"[0]pad"` //切换地图
|
Head player.TomeeHeader `cmd:"2003" struc:"[0]pad"` //切换地图
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListMapPlayerOutboundInfo struct {
|
|
||||||
PlayersLen uint32 `struc:"sizeof=Player" json:"player_len"`
|
|
||||||
|
|
||||||
// 穿戴装备的信息
|
|
||||||
Player []info.OutInfo ` json:"player"`
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
package maps
|
package maps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/logic/service/common"
|
|
||||||
"blazing/logic/service/player"
|
"blazing/logic/service/player"
|
||||||
"blazing/logic/service/space"
|
|
||||||
|
|
||||||
"blazing/modules/blazing/model"
|
"blazing/modules/blazing/model"
|
||||||
|
|
||||||
"golang.org/x/time/rate"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type WalkInInfo struct {
|
type WalkInInfo struct {
|
||||||
@@ -21,35 +17,3 @@ type WalkInInfo struct {
|
|||||||
PathLen uint32 `struc:"sizeof=Path" `
|
PathLen uint32 `struc:"sizeof=Path" `
|
||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
var limiter = rate.NewLimiter(rate.Limit(10), 5)
|
|
||||||
|
|
||||||
func (t *WalkInInfo) Broadcast(mapid uint32, o WalkOutInfo) {
|
|
||||||
// cool.Limiter.Take()
|
|
||||||
//r := cool.Limiter.Get("Broadcast"+gconv.String(mapid), rate.Limit(10), 5)
|
|
||||||
if !limiter.Allow() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
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
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// PeopleWalkOutboundInfo PeopleWalkOutboundInfo类,实现OutboundMessage接口
|
|
||||||
type WalkOutInfo struct {
|
|
||||||
// Flag: 0为走,1为飞行模式
|
|
||||||
Flag uint32 `fieldDesc:"0为走,1为飞行模式" codec:"uint"`
|
|
||||||
|
|
||||||
// UserID: 走动的人的米米号
|
|
||||||
UserID uint32 `fieldDesc:"走动的人的米米号" codec:"uint"`
|
|
||||||
|
|
||||||
// Point: 直接给坐标x,y
|
|
||||||
Point model.Pos `fieldDesc:"直接给坐标x,y"`
|
|
||||||
|
|
||||||
PathLen uint32 `struc:"sizeof=Path" `
|
|
||||||
Path string
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ type AI_player struct {
|
|||||||
func (f *AI_player) SendPack(b []byte) error {
|
func (f *AI_player) SendPack(b []byte) error {
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
func (p *AI_player) SendWalkMapInfo(b maps.WalkOutInfo) {
|
||||||
|
|
||||||
}
|
}
|
||||||
func (p *AI_player) SendLeaveMapInfo(b maps.LeaveMapOutboundInfo) {
|
func (p *AI_player) SendLeaveMapInfo(b maps.LeaveMapOutboundInfo) {
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,13 @@ func (p *Player) SendEnterMapInfo(b maps.OutInfo) {
|
|||||||
p.SendPack(t1.Pack(&b)) //准备包由各自发,因为协议不一样
|
p.SendPack(t1.Pack(&b)) //准备包由各自发,因为协议不一样
|
||||||
|
|
||||||
}
|
}
|
||||||
|
func (p *Player) SendWalkMapInfo(b maps.WalkOutInfo) {
|
||||||
|
t1 := NewTomeeHeader(2101, p.Info.UserID)
|
||||||
|
|
||||||
|
p.SendPack(t1.Pack(&b)) //准备包由各自发,因为协议不一样
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Player) SendChangePet(b info.ChangePetInfo) {
|
func (p *Player) SendChangePet(b info.ChangePetInfo) {
|
||||||
t1 := NewTomeeHeader(2407, p.Info.UserID)
|
t1 := NewTomeeHeader(2407, p.Info.UserID)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"blazing/common/utils"
|
"blazing/common/utils"
|
||||||
"blazing/cool"
|
"blazing/cool"
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
|
"blazing/logic/service/space"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -81,6 +82,9 @@ func (p *Player) UseCoins(t uint32) bool {
|
|||||||
}
|
}
|
||||||
func (p *Player) GetAction() {
|
func (p *Player) GetAction() {
|
||||||
|
|
||||||
|
}
|
||||||
|
func (p *Player) GetSpace() *space.Space {
|
||||||
|
return space.GetSpace(p.Info.MapID)
|
||||||
}
|
}
|
||||||
func (p *Player) CanFight() bool {
|
func (p *Player) CanFight() bool {
|
||||||
if p.FightC != nil {
|
if p.FightC != nil {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package space
|
package space
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/common/data/xmlres"
|
csmap "github.com/mhmtszr/concurrent-swiss-map"
|
||||||
|
|
||||||
"golang.org/x/sync/singleflight"
|
"golang.org/x/sync/singleflight"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -10,36 +9,60 @@ var requestGroup singleflight.Group // SingleFlight 实例
|
|||||||
// MapHotInfo 表示地图热度信息
|
// MapHotInfo 表示地图热度信息
|
||||||
type MapHotInfo struct {
|
type MapHotInfo struct {
|
||||||
MapID uint32 `json:"mapId"` // 地图ID
|
MapID uint32 `json:"mapId"` // 地图ID
|
||||||
Count uint32 `json:"count"` // 地图里的人数
|
Count int32 `struc:"uint32" json:"count"` // 地图里的人数
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var maphot = csmap.New[uint32, *int32](
|
||||||
|
// set the number of map shards. the default value is 32.
|
||||||
|
csmap.WithShardCount[uint32, *int32](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),
|
||||||
|
)
|
||||||
|
|
||||||
func GetMapHot() []MapHotInfo {
|
func GetMapHot() []MapHotInfo {
|
||||||
|
ret := make([]MapHotInfo, 0)
|
||||||
result1, _, _ := requestGroup.Do("map_hot", func() (interface{}, error) {
|
maphot.Range(func(key uint32, value *int32) (stop bool) {
|
||||||
|
ret = append(ret, MapHotInfo{
|
||||||
tt := make(map[uint32]uint32)
|
MapID: key,
|
||||||
|
Count: *value,
|
||||||
for _, v := range xmlres.MapConfig.Maps {
|
|
||||||
|
|
||||||
t1, ok := tt[uint32(v.Super)]
|
|
||||||
if ok {
|
|
||||||
tt[uint32(v.Super)] = uint32(int(t1) + GetSpace(uint32(v.ID)).User.Count())
|
|
||||||
|
|
||||||
} else {
|
|
||||||
tt[uint32(v.Super)] = uint32(GetSpace(uint32(v.ID)).User.Count())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
var result = make([]MapHotInfo, 0)
|
|
||||||
for k, v := range tt {
|
|
||||||
|
|
||||||
result = append(result, MapHotInfo{
|
|
||||||
MapID: uint32(k),
|
|
||||||
Count: uint32(v),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
return true
|
||||||
return result, nil
|
|
||||||
})
|
})
|
||||||
return result1.([]MapHotInfo)
|
return ret
|
||||||
|
// result1, _, _ := requestGroup.Do("map_hot", func() (interface{}, error) {
|
||||||
|
|
||||||
|
// tt := make(map[uint32]uint32)
|
||||||
|
|
||||||
|
// for _, v := range xmlres.MapConfig.Maps {
|
||||||
|
|
||||||
|
// t1, ok := tt[uint32(v.Super)]
|
||||||
|
// if ok {
|
||||||
|
// tt[uint32(v.Super)] = uint32(int(t1) + GetSpace(uint32(v.ID)).User.Count())
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// tt[uint32(v.Super)] = uint32(GetSpace(uint32(v.ID)).User.Count())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// var result = make([]MapHotInfo, 0)
|
||||||
|
// for k, v := range tt {
|
||||||
|
|
||||||
|
// result = append(result, MapHotInfo{
|
||||||
|
// MapID: uint32(k),
|
||||||
|
// Count: uint32(v),
|
||||||
|
// })
|
||||||
|
|
||||||
|
// }
|
||||||
|
// return result, nil
|
||||||
|
// })
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ package space
|
|||||||
import (
|
import (
|
||||||
"blazing/logic/service/common"
|
"blazing/logic/service/common"
|
||||||
"blazing/logic/service/maps/info"
|
"blazing/logic/service/maps/info"
|
||||||
|
maps "blazing/logic/service/maps/info"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
|
"golang.org/x/time/rate"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Space) LeaveMap(c common.PlayerI) {
|
func (s *Space) LeaveMap(c common.PlayerI) {
|
||||||
@@ -14,9 +17,6 @@ func (s *Space) LeaveMap(c common.PlayerI) {
|
|||||||
if c.GetInfo() == nil {
|
if c.GetInfo() == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if c.GetInfo().MapID == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.UP_ARENA(c, 0) //退出擂台
|
s.UP_ARENA(c, 0) //退出擂台
|
||||||
s.User.Range(func(k uint32, v common.PlayerI) (stop bool) {
|
s.User.Range(func(k uint32, v common.PlayerI) (stop bool) {
|
||||||
@@ -29,6 +29,12 @@ func (s *Space) LeaveMap(c common.PlayerI) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
s.User.Delete(c.GetInfo().UserID)
|
s.User.Delete(c.GetInfo().UserID)
|
||||||
|
s.UserInfo.Delete(c.GetInfo().UserID)
|
||||||
|
if s.SuperValue != nil {
|
||||||
|
|
||||||
|
atomic.AddInt32(s.SuperValue, -1)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Space) EnterMap(c common.PlayerI) {
|
func (s *Space) EnterMap(c common.PlayerI) {
|
||||||
@@ -36,10 +42,52 @@ func (s *Space) EnterMap(c common.PlayerI) {
|
|||||||
out := info.NewOutInfo()
|
out := info.NewOutInfo()
|
||||||
copier.CopyWithOption(out, c.GetInfo(), copier.Option{DeepCopy: true})
|
copier.CopyWithOption(out, c.GetInfo(), copier.Option{DeepCopy: true})
|
||||||
s.User.Range(func(k uint32, v common.PlayerI) (stop bool) {
|
s.User.Range(func(k uint32, v common.PlayerI) (stop bool) {
|
||||||
|
if k != c.GetInfo().UserID {
|
||||||
v.SendEnterMapInfo(*out)
|
v.SendEnterMapInfo(*out)
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
s.User.Store(c.GetInfo().UserID, c)
|
s.User.Store(c.GetInfo().UserID, c)
|
||||||
|
s.UserInfo.Store(c.GetInfo().UserID, *out)
|
||||||
|
if s.SuperValue != nil {
|
||||||
|
atomic.AddInt32(s.SuperValue, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func (s *Space) GetInfo() []maps.OutInfo {
|
||||||
|
ret := make([]maps.OutInfo, 0)
|
||||||
|
s.UserInfo.Range(func(k uint32, v maps.OutInfo) (stop bool) {
|
||||||
|
ret = append(ret, v)
|
||||||
|
return len(ret) > 30
|
||||||
|
})
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var limiter = rate.NewLimiter(rate.Limit(10), 5)
|
||||||
|
|
||||||
|
func (s *Space) Walk(b maps.WalkOutInfo) {
|
||||||
|
// cool.Limiter.Take()
|
||||||
|
//r := cool.Limiter.Get("Broadcast"+gconv.String(mapid), rate.Limit(10), 5)
|
||||||
|
if !limiter.Allow() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.User.Range(func(playerID uint32, player common.PlayerI) bool {
|
||||||
|
player.SendWalkMapInfo(b)
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func LastFourElements[T any](s []T) []T {
|
||||||
|
n := len(s)
|
||||||
|
if n <= 30 {
|
||||||
|
// 切片长度小于等于4时,返回整个切片
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
// 切片长度大于4时,返回最后4个元素(从n-4索引到末尾)
|
||||||
|
return s[n-30:]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"blazing/logic/service/common"
|
"blazing/logic/service/common"
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
|
maps "blazing/logic/service/maps/info"
|
||||||
|
|
||||||
csmap "github.com/mhmtszr/concurrent-swiss-map"
|
csmap "github.com/mhmtszr/concurrent-swiss-map"
|
||||||
)
|
)
|
||||||
@@ -13,7 +14,10 @@ import (
|
|||||||
// Space 针对Player的并发安全map,键为uint32类型
|
// Space 针对Player的并发安全map,键为uint32类型
|
||||||
type Space struct {
|
type Space struct {
|
||||||
User *csmap.CsMap[uint32, common.PlayerI] // 存储玩家数据的map,键为玩家ID
|
User *csmap.CsMap[uint32, common.PlayerI] // 存储玩家数据的map,键为玩家ID
|
||||||
|
UserInfo *csmap.CsMap[uint32, maps.OutInfo]
|
||||||
CanRefresh bool //是否能够刷怪
|
CanRefresh bool //是否能够刷怪
|
||||||
|
Super uint32
|
||||||
|
SuperValue *int32
|
||||||
//ID uint32 // 地图ID
|
//ID uint32 // 地图ID
|
||||||
Name string //地图名称
|
Name string //地图名称
|
||||||
ARENA info.S2C_ARENA_GET_INFO
|
ARENA info.S2C_ARENA_GET_INFO
|
||||||
@@ -93,6 +97,20 @@ func NewSpace() *Space {
|
|||||||
// return hash.Sum64()
|
// 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),
|
||||||
|
),
|
||||||
|
UserInfo: csmap.New[uint32, maps.OutInfo](
|
||||||
|
// set the number of map shards. the default value is 32.
|
||||||
|
csmap.WithShardCount[uint32, maps.OutInfo](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.
|
// set the total capacity, every shard map has total capacity/shard count capacity. the default value is 0.
|
||||||
// csmap.WithSize[string, int](1000),
|
// csmap.WithSize[string, int](1000),
|
||||||
),
|
),
|
||||||
@@ -113,6 +131,16 @@ func GetSpace(id uint32) *Space {
|
|||||||
for _, v := range xmlres.MapConfig.Maps {
|
for _, v := range xmlres.MapConfig.Maps {
|
||||||
if v.ID == int(id) { //找到这个地图
|
if v.ID == int(id) { //找到这个地图
|
||||||
t := NewSpace()
|
t := NewSpace()
|
||||||
|
t.Super = uint32(v.Super)
|
||||||
|
ok := maphot.Has(t.Super)
|
||||||
|
if !ok {
|
||||||
|
var tt int32 = 0
|
||||||
|
maphot.Store(uint32(v.Super), &tt)
|
||||||
|
t.SuperValue = &tt //创建一个
|
||||||
|
|
||||||
|
} else {
|
||||||
|
t.SuperValue, _ = maphot.Load(uint32(v.Super))
|
||||||
|
}
|
||||||
|
|
||||||
t.Name = v.Name
|
t.Name = v.Name
|
||||||
|
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ type CompleteTaskOutboundInfo struct {
|
|||||||
// 用于表示发放物品的信息
|
// 用于表示发放物品的信息
|
||||||
type ItemInfo struct {
|
type ItemInfo struct {
|
||||||
ItemId uint32 `json:"itemId" description:"发放物品ID"` // 发放物品ID,
|
ItemId uint32 `json:"itemId" description:"发放物品ID"` // 发放物品ID,
|
||||||
ItemCount uint32 `json:"itemCount" description:"发放物品的数量"` // 发放物品的数量,
|
ItemCnt uint32 `json:"itemCount" description:"发放物品的数量"` // 发放物品的数量,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func init() {
|
|||||||
{300011, 3}, // 初级体力药剂x3
|
{300011, 3}, // 初级体力药剂x3
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
RegisterTask(88, 0, []ItemInfo{ // 新手任务4(默认分支)
|
RegisterTask(88, 1, []ItemInfo{ // 新手任务4(默认分支)
|
||||||
{1, 50000}, // 赛尔豆x50000
|
{1, 50000}, // 赛尔豆x50000
|
||||||
{3, 50000}, // 累积经验x50000
|
{3, 50000}, // 累积经验x50000
|
||||||
{5, 20}, // 金豆x20
|
{5, 20}, // 金豆x20
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package task
|
package task
|
||||||
|
|
||||||
|
|
||||||
type TaskResult struct {
|
type TaskResult struct {
|
||||||
PetTypeId uint32 `json:"petTypeId" description:"发放的精灵ID"` // 发放的精灵ID,
|
PetTypeId uint32 `json:"petTypeId" description:"发放的精灵ID"` // 发放的精灵ID,
|
||||||
|
|
||||||
@@ -19,9 +18,9 @@ func Get_Task_Info(v CompleteTaskInboundInfo) *TaskResult {
|
|||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
// 定义通用奖励:经验奖励(ItemId:3,数量20000)
|
// 定义通用奖励:经验奖励(ItemId:3,数量20000)
|
||||||
expReward := []ItemInfo{{ItemId: 3, ItemCount: 20000}}
|
expReward := []ItemInfo{{ItemId: 3, ItemCnt: 20000}}
|
||||||
// 定义扭蛋牌奖励(ItemId:400501,数量5)
|
// 定义扭蛋牌奖励(ItemId:400501,数量5)
|
||||||
eggReward := []ItemInfo{{ItemId: 400501, ItemCount: 5}}
|
eggReward := []ItemInfo{{ItemId: 400501, ItemCnt: 5}}
|
||||||
|
|
||||||
// 批量初始化任务ID 401-407(奖励均为经验)
|
// 批量初始化任务ID 401-407(奖励均为经验)
|
||||||
for taskID := 401; taskID <= 407; taskID++ {
|
for taskID := 401; taskID <= 407; taskID++ {
|
||||||
|
|||||||
Reference in New Issue
Block a user