feat(cache): 添加复合键缓存操作支持 添加了基于 uint32+string 组合键的缓存操作方法,包括 GetByCompoundKey、SetByCompoundKey、DelByCompoundKey 和 ContainsByCompoundKey 方法,用于处理用户ID和会话ID的组合缓存场景 fix(vscode): 添加 cSpell 配置支持 struc 词汇 refactor(session): 移除过时的会话管理方法 移除了基于单一字符串键的会话管理方法,因为已迁移到使用 复合键的缓存操作方式 ```
94 lines
2.6 KiB
Go
94 lines
2.6 KiB
Go
package player
|
||
|
||
import (
|
||
"blazing/modules/player/model"
|
||
)
|
||
|
||
type Done struct {
|
||
*Player //对玩家进行操作
|
||
// *bus.Topic[*model.MilestoneEX]
|
||
}
|
||
|
||
func NewDone(P *Player) Done {
|
||
return Done{
|
||
Player: P,
|
||
/// Topic: bus.NewTopic[*model.MilestoneEX](),
|
||
}
|
||
|
||
}
|
||
|
||
// 注册地图BOSS完成事件
|
||
// MAPID 地图ID
|
||
// BOSSID 地图BOSSID
|
||
// 注册胜利次数
|
||
// 监听器返回奖励是否发送完成,完成就done
|
||
// func (d *Done) SPT(mapid, bossid, count uint32, fn func() bool) *bus.Listener[*model.MilestoneEX] {
|
||
// return d.Topic.Sub(func(v *model.MilestoneEX) {
|
||
// //然后每次触发使用前缀匹配,只要前缀满足就触发
|
||
// if v.DoneType == model.MilestoneMode.BOSS && IsPrefixBasicSlice(v.Args, []uint32{mapid, bossid}) && v.Count == count {
|
||
|
||
// _, ok := lo.Find(v.Args, func(v1 uint32) bool { //寻找是否触发过
|
||
// //大于触发值就触发,然后1的返回false,因为没有奖励,这样就可以一直触发
|
||
// return v1 >= count //大于等于就触发
|
||
// })
|
||
// if !ok { //说明没有触发过
|
||
|
||
// if fn() {
|
||
// v.Results = append(v.Results, count) //把本次的记录添加
|
||
// }
|
||
|
||
// }
|
||
|
||
// }
|
||
|
||
// })
|
||
|
||
// }
|
||
|
||
// 分发事件 ,指定事件+1 并触发是否完成
|
||
func (d *Player) Exec(Donetype model.EnumMilestone, id []uint32, fn func(*model.MilestoneEX) uint32) {
|
||
|
||
d.Service.Done.Exec(Donetype, id, func(t *model.MilestoneEX) bool {
|
||
//这里给予即时奖励,并将用户计数+1
|
||
t.Count++
|
||
//然后有需要自动发送奖励地方,发送完奖励给置真
|
||
|
||
if fn != nil {
|
||
t1 := fn(t)
|
||
if t1 != 0 {
|
||
t.Results = append(t.Results, t1) //把本次的记录添加
|
||
}
|
||
}
|
||
|
||
// d.Topic.Pub(t) //异步发送,然后给事件+1
|
||
|
||
// d.Topic.PubAsyncCallBack(s, func() { //如果没执行完,说明奖励没发完,直接掉线
|
||
// d.Service.Done.Exec(s) //给计数器加1
|
||
// }) //提交触发里程碑奖励
|
||
return true
|
||
}) //给计数器加1
|
||
}
|
||
|
||
// IsPrefixBasicSlice 判断切片 B 是否是切片 A 的前缀
|
||
// 泛型约束支持 int | string | bool | uint32 类型的切片
|
||
// 规则:
|
||
// 1. 若 B 长度 > A 长度 → 直接返回 false
|
||
// 2. 若 B 为空切片 → 返回 true(空切片是任何切片的前缀)
|
||
// 3. 遍历 B 的每个元素,与 A 对应位置元素逐一比对,全部相等则返回 true
|
||
func IsPrefixBasicSlice[T int | string | bool | uint32](a, b []T) bool {
|
||
// 前置判断:B 更长则不可能是 A 的前缀
|
||
if len(b) > len(a) {
|
||
return false
|
||
}
|
||
|
||
// 遍历 B 的所有元素,比对 A 前 len(b) 个元素
|
||
for i := range b {
|
||
if a[i] != b[i] {
|
||
return false
|
||
}
|
||
}
|
||
|
||
// 所有校验通过
|
||
return true
|
||
}
|