每日任务添加
This commit is contained in:
@@ -12,61 +12,190 @@ import (
|
|||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newDailyCounterStore 创建每日计数器缓存实例
|
// 周期类型定义
|
||||||
func newDailyCounterStore() *cacheStore[int64] {
|
type PeriodType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
PeriodDaily PeriodType = 1 // 每日
|
||||||
|
PeriodWeekly PeriodType = 2 // 每周
|
||||||
|
PeriodMonthly PeriodType = 3 // 每月
|
||||||
|
PeriodQuarter PeriodType = 4 // 每季
|
||||||
|
)
|
||||||
|
|
||||||
|
// 周期函数类型定义
|
||||||
|
type (
|
||||||
|
// FormatFunc 生成周期格式化字符串的函数
|
||||||
|
FormatFunc func(t time.Time) string
|
||||||
|
|
||||||
|
// ExpireFunc 计算周期过期时间的函数
|
||||||
|
ExpireFunc func(t time.Time) time.Duration
|
||||||
|
)
|
||||||
|
|
||||||
|
// Period 周期结构体,聚合周期相关函数和元信息
|
||||||
|
type Period struct {
|
||||||
|
Type PeriodType // 周期类型
|
||||||
|
Format FormatFunc // 周期格式化函数
|
||||||
|
Expire ExpireFunc // 过期时间计算函数
|
||||||
|
Prefix string // 缓存键前缀
|
||||||
|
}
|
||||||
|
|
||||||
|
// 周期实例 - 每日
|
||||||
|
var DailyPeriod = Period{
|
||||||
|
Type: PeriodDaily,
|
||||||
|
Format: func(t time.Time) string {
|
||||||
|
return t.Format("20060102") // 格式: YYYYMMDD
|
||||||
|
},
|
||||||
|
Expire: func(t time.Time) time.Duration {
|
||||||
|
tomorrow := t.AddDate(0, 0, 1)
|
||||||
|
resetTime := time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, time.Local)
|
||||||
|
return resetTime.Sub(t)
|
||||||
|
},
|
||||||
|
Prefix: "daily:",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 周期实例 - 每周
|
||||||
|
var WeeklyPeriod = Period{
|
||||||
|
Type: PeriodWeekly,
|
||||||
|
Format: func(t time.Time) string {
|
||||||
|
// 计算当年第几周 (ISO周编号)
|
||||||
|
year, week := t.ISOWeek()
|
||||||
|
return fmt.Sprintf("%dW%02d", year, week) // 格式: YYYYWww
|
||||||
|
},
|
||||||
|
Expire: func(t time.Time) time.Duration {
|
||||||
|
// 计算下周一0点
|
||||||
|
weekday := t.Weekday()
|
||||||
|
daysToNextMonday := (8 - int(weekday)) % 7
|
||||||
|
nextMonday := t.AddDate(0, 0, daysToNextMonday)
|
||||||
|
resetTime := time.Date(nextMonday.Year(), nextMonday.Month(), nextMonday.Day(), 0, 0, 0, 0, time.Local)
|
||||||
|
return resetTime.Sub(t)
|
||||||
|
},
|
||||||
|
Prefix: "weekly:",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 周期实例 - 每月
|
||||||
|
var MonthlyPeriod = Period{
|
||||||
|
Type: PeriodMonthly,
|
||||||
|
Format: func(t time.Time) string {
|
||||||
|
return t.Format("200601") // 格式: YYYYMM
|
||||||
|
},
|
||||||
|
Expire: func(t time.Time) time.Duration {
|
||||||
|
// 计算下月1日0点
|
||||||
|
nextMonth := t.AddDate(0, 1, 0)
|
||||||
|
resetTime := time.Date(nextMonth.Year(), nextMonth.Month(), 1, 0, 0, 0, 0, time.Local)
|
||||||
|
return resetTime.Sub(t)
|
||||||
|
},
|
||||||
|
Prefix: "monthly:",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 周期实例 - 每季
|
||||||
|
var QuarterlyPeriod = Period{
|
||||||
|
Type: PeriodQuarter,
|
||||||
|
Format: func(t time.Time) string {
|
||||||
|
quarter := (int(t.Month())-1)/3 + 1
|
||||||
|
return fmt.Sprintf("%dQ%d", t.Year(), quarter) // 格式: YYYYQq
|
||||||
|
},
|
||||||
|
Expire: func(t time.Time) time.Duration {
|
||||||
|
// 计算下季首月1日0点
|
||||||
|
quarter := (int(t.Month())-1)/3 + 1
|
||||||
|
nextQuarterFirstMonth := quarter*3 + 1
|
||||||
|
year := t.Year()
|
||||||
|
if nextQuarterFirstMonth > 12 {
|
||||||
|
nextQuarterFirstMonth = 1
|
||||||
|
year++
|
||||||
|
}
|
||||||
|
resetTime := time.Date(year, time.Month(nextQuarterFirstMonth), 1, 0, 0, 0, 0, time.Local)
|
||||||
|
return resetTime.Sub(t)
|
||||||
|
},
|
||||||
|
Prefix: "quarterly:",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 周期映射表,用于快速查找周期实例
|
||||||
|
var periodMap = map[PeriodType]*Period{
|
||||||
|
PeriodDaily: &DailyPeriod,
|
||||||
|
PeriodWeekly: &WeeklyPeriod,
|
||||||
|
PeriodMonthly: &MonthlyPeriod,
|
||||||
|
PeriodQuarter: &QuarterlyPeriod,
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPeriodByType 根据周期类型获取周期实例
|
||||||
|
func GetPeriodByType(periodType PeriodType) (*Period, error) {
|
||||||
|
period, ok := periodMap[periodType]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("不支持的周期类型: %d", periodType)
|
||||||
|
}
|
||||||
|
return period, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// newCounterStore 创建计数器缓存实例
|
||||||
|
func newCounterStore(period *Period) *cacheStore[int64] {
|
||||||
return &cacheStore[int64]{
|
return &cacheStore[int64]{
|
||||||
manager: cool.CacheManager,
|
manager: cool.CacheManager,
|
||||||
prefix: "blazing:dailycounter:",
|
prefix: fmt.Sprintf("blazing:counter:%s", period.Prefix),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCounterLimitStore 创建计数器限制配置缓存实例
|
// newLimitStore 创建限制配置缓存实例
|
||||||
func newCounterLimitStore() *cacheStore[int64] {
|
func newLimitStore() *cacheStore[int64] {
|
||||||
return &cacheStore[int64]{
|
return &cacheStore[int64]{
|
||||||
manager: cool.CacheManager,
|
manager: cool.CacheManager,
|
||||||
prefix: "blazing:counterlimit:",
|
prefix: "blazing:counterlimit:",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// counterManager 计数器管理器(每日计数+限制配置+批量查询)
|
// CounterManager 计数器管理器
|
||||||
type counterManager struct {
|
type CounterManager struct {
|
||||||
dailyCounterStore *cacheStore[int64] // 每日计数器缓存
|
limitStore *cacheStore[int64] // 限制配置缓存
|
||||||
counterLimitStore *cacheStore[int64] // 计数器限制配置缓存
|
periods map[PeriodType]*cacheStore[int64] // 各周期计数器缓存
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCounterManager 创建计数器管理器实例
|
// NewCounterManager 创建计数器管理器实例
|
||||||
func newCounterManager() *counterManager {
|
func NewCounterManager() *CounterManager {
|
||||||
return &counterManager{
|
// 初始化所有周期的缓存存储
|
||||||
dailyCounterStore: newDailyCounterStore(),
|
periods := make(map[PeriodType]*cacheStore[int64])
|
||||||
counterLimitStore: newCounterLimitStore(),
|
for _, period := range periodMap {
|
||||||
|
periods[period.Type] = newCounterStore(period)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CounterManager{
|
||||||
|
limitStore: newLimitStore(),
|
||||||
|
periods: periods,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// genDailyKey 生成单个奖品类型的每日计数键
|
// genKey 生成计数器键
|
||||||
// 格式:{userID}:{rewardType}:{date}(userID和rewardType为uint32)
|
func (m *CounterManager) genKey(period *Period, userID uint32, rewardType uint32) string {
|
||||||
func (m *counterManager) genDailyKey(userID uint32, rewardType uint32) string {
|
periodStr := period.Format(time.Now())
|
||||||
date := time.Now().Format("20060102") // 当日日期(YYYYMMDD)
|
return fmt.Sprintf("%d:%d:%s", userID, rewardType, periodStr)
|
||||||
return fmt.Sprintf("%d:%d:%s", userID, rewardType, date)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// genUserDailyPrefix 生成用户当日所有计数的键前缀(用于扫描)
|
// genUserPrefix 生成用户某周期所有计数的键前缀
|
||||||
func (m *counterManager) genUserDailyPrefix(userID uint32) string {
|
func (m *CounterManager) genUserPrefix(period *Period, userID uint32) string {
|
||||||
date := time.Now().Format("20060102")
|
periodStr := period.Format(time.Now())
|
||||||
return fmt.Sprintf("%d:*:%s", userID, date) // 格式:{userID}:*:{date}
|
return fmt.Sprintf("%d:*:%s", userID, periodStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDailyCount 获取用户当日某奖品的计数
|
// GetCount 获取用户某周期某奖品的计数
|
||||||
func (m *counterManager) GetDailyCount(userID uint32, rewardType uint32) (int64, error) {
|
func (m *CounterManager) GetCount(period *Period, userID uint32, rewardType uint32) (int64, error) {
|
||||||
key := m.genDailyKey(userID, rewardType)
|
store, ok := m.periods[period.Type]
|
||||||
return m.dailyCounterStore.Get(context.Background(), key)
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("不支持的周期类型: %d", period.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
key := m.genKey(period, userID, rewardType)
|
||||||
|
return store.Get(context.Background(), key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrDailyCount 增加用户当日某奖品的计数(自动设置次日0点过期)
|
// IncrCount 增加用户某周期某奖品的计数(自动设置周期结束过期)
|
||||||
func (m *counterManager) IncrDailyCount(userID uint32, rewardType uint32) (int64, error) {
|
func (m *CounterManager) IncrCount(period *Period, userID uint32, rewardType uint32) (int64, error) {
|
||||||
key := m.genDailyKey(userID, rewardType)
|
store, ok := m.periods[period.Type]
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("不支持的周期类型: %d", period.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
key := m.genKey(period, userID, rewardType)
|
||||||
|
|
||||||
// 获取当前计数(不存在则视为0)
|
// 获取当前计数(不存在则视为0)
|
||||||
current, err := m.dailyCounterStore.Get(context.Background(), key)
|
current, err := store.Get(context.Background(), key)
|
||||||
if err != nil && err != ErrCacheMiss {
|
if err != nil && err != ErrCacheMiss {
|
||||||
return 0, fmt.Errorf("获取当前计数失败: %w", err)
|
return 0, fmt.Errorf("获取当前计数失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -77,40 +206,43 @@ func (m *counterManager) IncrDailyCount(userID uint32, rewardType uint32) (int64
|
|||||||
// 计算新计数
|
// 计算新计数
|
||||||
newValue := current + 1
|
newValue := current + 1
|
||||||
|
|
||||||
// 计算过期时间:到次日0点(确保当日数据自动重置)
|
// 计算过期时间
|
||||||
tomorrow := time.Now().AddDate(0, 0, 1)
|
ttl := period.Expire(time.Now())
|
||||||
resetTime := time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, time.Local)
|
|
||||||
ttl := resetTime.Sub(time.Now())
|
|
||||||
|
|
||||||
// 保存新计数并设置过期时间
|
// 保存新计数并设置过期时间
|
||||||
if err := m.dailyCounterStore.Set(gctx.New(), key, newValue, ttl); err != nil {
|
if err := store.Set(gctx.New(), key, newValue, ttl); err != nil {
|
||||||
return 0, fmt.Errorf("保存计数失败: %w", err)
|
return 0, fmt.Errorf("保存计数失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newValue, nil
|
return newValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetDailyCount 重置用户当日某奖品的计数
|
// ResetCount 重置用户某周期某奖品的计数
|
||||||
func (m *counterManager) ResetDailyCount(userID uint32, rewardType uint32) error {
|
func (m *CounterManager) ResetCount(period *Period, userID uint32, rewardType uint32) error {
|
||||||
key := m.genDailyKey(userID, rewardType)
|
store, ok := m.periods[period.Type]
|
||||||
return m.dailyCounterStore.Del(gctx.New(), key)
|
if !ok {
|
||||||
|
return fmt.Errorf("不支持的周期类型: %d", period.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
key := m.genKey(period, userID, rewardType)
|
||||||
|
return store.Del(gctx.New(), key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCounterLimit 设置某奖品类型的每日限制
|
// SetLimit 设置某周期某奖品类型的限制
|
||||||
func (m *counterManager) SetCounterLimit(rewardType uint32, limit int64) error {
|
func (m *CounterManager) SetLimit(period *Period, rewardType uint32, limit int64) error {
|
||||||
key := fmt.Sprintf("%d", rewardType) // 限制键直接使用奖品类型(uint32)
|
key := fmt.Sprintf("%d:%d", period.Type, rewardType)
|
||||||
return m.counterLimitStore.Set(gctx.New(), key, limit, time.Hour*24*7) // 限制配置保留7天
|
return m.limitStore.Set(gctx.New(), key, limit, time.Hour*24*7) // 限制配置保留7天
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCounterLimit 获取某奖品类型的每日限制
|
// GetLimit 获取某周期某奖品类型的限制
|
||||||
func (m *counterManager) GetCounterLimit(rewardType uint32) (int64, error) {
|
func (m *CounterManager) GetLimit(period *Period, rewardType uint32) (int64, error) {
|
||||||
key := fmt.Sprintf("%d", rewardType)
|
key := fmt.Sprintf("%d:%d", period.Type, rewardType)
|
||||||
return m.counterLimitStore.Get(context.Background(), key)
|
return m.limitStore.Get(context.Background(), key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsExceedLimit 检查用户当日某奖品的计数是否超过限制
|
// IsExceedLimit 检查用户某周期某奖品的计数是否超过限制
|
||||||
func (m *counterManager) IsExceedLimit(userID uint32, rewardType uint32) (bool, error) {
|
func (m *CounterManager) IsExceedLimit(period *Period, userID uint32, rewardType uint32) (bool, error) {
|
||||||
count, err := m.GetDailyCount(userID, rewardType)
|
count, err := m.GetCount(period, userID, rewardType)
|
||||||
if err != nil && err != ErrCacheMiss {
|
if err != nil && err != ErrCacheMiss {
|
||||||
return false, fmt.Errorf("获取计数失败: %w", err)
|
return false, fmt.Errorf("获取计数失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -119,7 +251,7 @@ func (m *counterManager) IsExceedLimit(userID uint32, rewardType uint32) (bool,
|
|||||||
count = 0
|
count = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
limit, err := m.GetCounterLimit(rewardType)
|
limit, err := m.GetLimit(period, rewardType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("获取限制失败: %w", err)
|
return false, fmt.Errorf("获取限制失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -127,20 +259,24 @@ func (m *counterManager) IsExceedLimit(userID uint32, rewardType uint32) (bool,
|
|||||||
return count >= limit, nil
|
return count >= limit, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserAllDailyCounts 获取用户当日所有奖品类型的计数
|
// GetUserAllCounts 获取用户某周期所有奖品类型的计数
|
||||||
func (m *counterManager) GetUserAllDailyCounts(userID uint32) (map[uint32]int64, error) {
|
func (m *CounterManager) GetUserAllCounts(period *Period, userID uint32) (map[uint32]int64, error) {
|
||||||
// 1. 生成扫描模式(包含缓存前缀,使用*通配符)
|
store, ok := m.periods[period.Type]
|
||||||
// 格式:blazing:dailycounter:{userID}:*:{今日日期}
|
if !ok {
|
||||||
today := time.Now().Format("20060102")
|
return nil, fmt.Errorf("不支持的周期类型: %d", period.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 生成扫描模式
|
||||||
|
periodStr := period.Format(time.Now())
|
||||||
matchPattern := fmt.Sprintf(
|
matchPattern := fmt.Sprintf(
|
||||||
"%s%d:*:%s",
|
"%s%d:*:%s",
|
||||||
m.dailyCounterStore.prefix,
|
store.prefix,
|
||||||
userID,
|
userID,
|
||||||
today,
|
periodStr,
|
||||||
)
|
)
|
||||||
|
|
||||||
// 2. 扫描所有匹配的键(通过Scan方法筛选)
|
// 2. 扫描所有匹配的键
|
||||||
keys, err := m.dailyCounterStore.Scan(context.Background(), matchPattern)
|
keys, err := store.Scan(context.Background(), matchPattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("扫描键失败: %w", err)
|
return nil, fmt.Errorf("扫描键失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -150,16 +286,16 @@ func (m *counterManager) GetUserAllDailyCounts(userID uint32) (map[uint32]int64,
|
|||||||
|
|
||||||
// 3. 提取核心键(去除缓存前缀)
|
// 3. 提取核心键(去除缓存前缀)
|
||||||
coreKeys := make([]string, 0, len(keys))
|
coreKeys := make([]string, 0, len(keys))
|
||||||
prefixLen := len(m.dailyCounterStore.prefix)
|
prefixLen := len(store.prefix)
|
||||||
for _, fullKey := range keys {
|
for _, fullKey := range keys {
|
||||||
if strings.HasPrefix(fullKey, m.dailyCounterStore.prefix) {
|
if strings.HasPrefix(fullKey, store.prefix) {
|
||||||
coreKey := fullKey[prefixLen:] // 核心键格式:userID:rewardType:date
|
coreKey := fullKey[prefixLen:] // 核心键格式:userID:rewardType:periodStr
|
||||||
coreKeys = append(coreKeys, coreKey)
|
coreKeys = append(coreKeys, coreKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 批量获取计数
|
// 4. 批量获取计数
|
||||||
values, err := m.dailyCounterStore.MGet(context.Background(), coreKeys)
|
values, err := store.MGet(context.Background(), coreKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("批量获取计数失败: %w", err)
|
return nil, fmt.Errorf("批量获取计数失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -173,16 +309,16 @@ func (m *counterManager) GetUserAllDailyCounts(userID uint32) (map[uint32]int64,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证用户ID(防止异常键干扰)
|
// 验证用户ID
|
||||||
parsedUserID, err := strconv.ParseUint(parts[0], 10, 32)
|
parsedUserID, err := strconv.ParseUint(parts[0], 10, 32)
|
||||||
if err != nil || uint32(parsedUserID) != userID {
|
if err != nil || uint32(parsedUserID) != userID {
|
||||||
fmt.Printf("[WARN] 忽略用户不匹配的键: %s\n", coreKey)
|
fmt.Printf("[WARN] 忽略用户不匹配的键: %s\n", coreKey)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证日期(确保是今日)
|
// 验证周期
|
||||||
if parts[2] != today {
|
if parts[2] != periodStr {
|
||||||
fmt.Printf("[WARN] 忽略过期键: %s(日期不匹配)\n", coreKey)
|
fmt.Printf("[WARN] 忽略过期键: %s(周期不匹配)\n", coreKey)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,5 +342,5 @@ func (m *counterManager) GetUserAllDailyCounts(userID uint32) (map[uint32]int64,
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 全局计数器管理器实例(根据实际需求初始化)
|
// 全局计数器管理器实例
|
||||||
var CounterManager = newCounterManager()
|
var GlobalCounterManager = NewCounterManager()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func (h Controller) AcceptTask(data *task.AcceptTaskInboundInfo, c *entity.Playe
|
|||||||
ft, ok := ttt[data.TaskId]
|
ft, ok := ttt[data.TaskId]
|
||||||
if ok { //如果找到任务
|
if ok { //如果找到任务
|
||||||
if ft.Status == 0 { //可以接受
|
if ft.Status == 0 { //可以接受
|
||||||
ft.Status = 1
|
ft.Status = 1 //接受
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
func (this *EffectNode) BeforeUseSkillCheck() bool {
|
func (this *EffectNode) UseSkill() bool {
|
||||||
panic("not implemented") // TODO: Implement
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *EffectNode) AfterUseSkillCheck() bool {
|
|
||||||
panic("not implemented") // TODO: Implement
|
panic("not implemented") // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
package info
|
package info
|
||||||
|
|
||||||
type Effect interface {
|
type Effect interface {
|
||||||
PreBattleStart() bool //战斗开始前
|
OnBattleStart() bool //战斗开始
|
||||||
OnBattleStart() bool //战斗开始
|
|
||||||
|
|
||||||
PreTurnStart() bool //回合开始前
|
OnTurnStart() bool //回合开始
|
||||||
OnTurnStart() bool //回合开始
|
|
||||||
|
OnActive() bool //效果生效
|
||||||
|
UseSkill() bool //使用技能
|
||||||
|
|
||||||
PreActive() bool //效果生效前
|
|
||||||
OnActive() bool //效果生效
|
|
||||||
BeforeUseSkillCheck() bool //使用技能前
|
|
||||||
AfterUseSkillCheck() bool //使用技能后
|
|
||||||
SkillUseEnd() bool //技能使用结束
|
|
||||||
BeforeMultiHit() bool //多段攻击前
|
BeforeMultiHit() bool //多段攻击前
|
||||||
BeforeHit() bool //命中前
|
BeforeHit() bool //命中前
|
||||||
OnCritPreDamage() bool //暴击判定成功且伤害计算前触发
|
OnCritPreDamage() bool //暴击判定成功且伤害计算前触发
|
||||||
|
|||||||
4
modules/blazing/model/cycle.go
Normal file
4
modules/blazing/model/cycle.go
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// /这里实现周期性任务,比如每日任务,每周任务,每月任务,每年任务,一次性任务
|
||||||
|
type PeriodType int
|
||||||
48
modules/blazing/model/task_Daily.go
Normal file
48
modules/blazing/model/task_Daily.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blazing/cool"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const TableNameDailyTask = "DailyTask"
|
||||||
|
|
||||||
|
// DailyTask mapped from table <DailyTask>
|
||||||
|
type DailyTask struct {
|
||||||
|
*cool.Model
|
||||||
|
PlayerID uint64 `gorm:"not null;index:idx_DailyTask_by_player_id;comment:'所属玩家ID'" json:"player_id"`
|
||||||
|
Data string `gorm:"type:text;not null;comment:'全部数据'" json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DailyTaskInfo 单个任务的详细信息,包含任务步骤状态和整体状态
|
||||||
|
type DailyTaskInfo struct {
|
||||||
|
// DailyTaskInfo 任务步骤信息,对应Java的@ArraySerialize(FIXED_LENGTH=20)注解
|
||||||
|
// struc:"[20]byte" 确保二进制序列化时固定20字节长度,json标签指定JSON字段名
|
||||||
|
DailyTaskInfo []uint32 `struc:"[20]byte" json:"DailyTask_info"`
|
||||||
|
LastResetTime time.Time `gorm:"not null;comment:'上次重置时间(UTC)'" json:"last_reset_time"` //这里是每天重置
|
||||||
|
// Status 任务整体状态:0-未接受,1-已接受,2-已完成未领取,3-已完成已领取
|
||||||
|
// json标签指定JSON字段名,与业务状态说明保持一致
|
||||||
|
Status byte `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName PlayerInfo's table name
|
||||||
|
func (*DailyTask) TableName() string {
|
||||||
|
return TableNamePlayerInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupName PlayerInfo's table group
|
||||||
|
func (*DailyTask) GroupName() string {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPlayerInfo create a new PlayerInfo
|
||||||
|
func NewDailyTask() *DailyTask {
|
||||||
|
return &DailyTask{
|
||||||
|
Model: cool.NewModel(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// init 创建表
|
||||||
|
func init() {
|
||||||
|
cool.CreateTable(&DailyTask{})
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"blazing/modules/blazing/model"
|
"blazing/modules/blazing/model"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Exec[T, F any](userid uint32, s *cool.Service, processFunc func(F) bool) bool {
|
func Exec[T, F any](userid uint32, s *cool.Service, processFunc func(F) bool) bool {
|
||||||
@@ -33,7 +34,46 @@ func Exec[T, F any](userid uint32, s *cool.Service, processFunc func(F) bool) bo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func (s *UserService) TaskExec(t func(map[uint32]model.TaskInfo) bool) (ret bool) {
|
func (s *UserService) TaskExec(t func(map[uint32]model.TaskInfo) bool) (ret bool) {
|
||||||
return Exec[model.Task, map[uint32]model.TaskInfo](s.userid, s.task, t)
|
return Exec[model.Task](s.userid, s.task, t)
|
||||||
|
// m := cool.DBM(s.task.Model).Where("player_id", s.userid)
|
||||||
|
// var tt model.Task
|
||||||
|
// m.Scan(&tt)
|
||||||
|
// var ttt map[uint32]model.TaskInfo
|
||||||
|
// json.Unmarshal([]byte(tt.Data), &ttt)
|
||||||
|
// ret = t(ttt)
|
||||||
|
// t1, _ := json.Marshal(&ttt)
|
||||||
|
// tt.Data = string(t1)
|
||||||
|
// m.Save(&tt) //退出时保存
|
||||||
|
// return
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsToday 判断给定时间是否是今天
|
||||||
|
func IsToday(t time.Time) bool {
|
||||||
|
// 获取当前时间
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
// 比较年、月、日是否相同
|
||||||
|
return t.Year() == now.Year() &&
|
||||||
|
t.Month() == now.Month() &&
|
||||||
|
t.Day() == now.Day()
|
||||||
|
}
|
||||||
|
func (s *UserService) DailyTaskExec(t func(map[uint32]model.DailyTaskInfo) bool) (ret bool) {
|
||||||
|
Exec[model.DailyTask](s.userid, s.task, func(tt map[uint32]model.DailyTaskInfo) bool {
|
||||||
|
|
||||||
|
//先重置每日
|
||||||
|
for _, v := range tt {
|
||||||
|
if !IsToday(v.LastResetTime) {
|
||||||
|
|
||||||
|
v.Status = 0 //重置+自动接受每日任务
|
||||||
|
v.LastResetTime = time.Now().UTC()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return Exec[model.DailyTask](s.userid, s.task, t)
|
||||||
// m := cool.DBM(s.task.Model).Where("player_id", s.userid)
|
// m := cool.DBM(s.task.Model).Where("player_id", s.userid)
|
||||||
// var tt model.Task
|
// var tt model.Task
|
||||||
// m.Scan(&tt)
|
// m.Scan(&tt)
|
||||||
|
|||||||
Reference in New Issue
Block a user