refactor: #60 重构 game/task 包,支持更灵活的任务配置方式
This commit is contained in:
parent
2079e9595e
commit
98c1f39ce6
|
@ -0,0 +1,142 @@
|
|||
package task
|
||||
|
||||
import "time"
|
||||
|
||||
// Cond 创建任务条件
|
||||
func Cond(k, v any) Condition {
|
||||
return map[any]any{k: v}
|
||||
}
|
||||
|
||||
// Condition 任务条件
|
||||
type Condition map[any]any
|
||||
|
||||
// Cond 创建任务条件
|
||||
func (slf Condition) Cond(k, v any) Condition {
|
||||
slf[k] = v
|
||||
return slf
|
||||
}
|
||||
|
||||
// GetString 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetString(key any) string {
|
||||
v, _ := slf[key].(string)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetInt 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetInt(key any) int {
|
||||
v, _ := slf[key].(int)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetInt8 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetInt8(key any) int8 {
|
||||
v, _ := slf[key].(int8)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetInt16 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetInt16(key any) int16 {
|
||||
v, _ := slf[key].(int16)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetInt32 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetInt32(key any) int32 {
|
||||
v, _ := slf[key].(int32)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetInt64 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetInt64(key any) int64 {
|
||||
v, _ := slf[key].(int64)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetUint 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetUint(key any) uint {
|
||||
v, _ := slf[key].(uint)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetUint8 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetUint8(key any) uint8 {
|
||||
v, _ := slf[key].(uint8)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetUint16 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetUint16(key any) uint16 {
|
||||
v, _ := slf[key].(uint16)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetUint32 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetUint32(key any) uint32 {
|
||||
v, _ := slf[key].(uint32)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetUint64 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetUint64(key any) uint64 {
|
||||
v, _ := slf[key].(uint64)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetFloat32 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetFloat32(key any) float32 {
|
||||
v, _ := slf[key].(float32)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetFloat64 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetFloat64(key any) float64 {
|
||||
v, _ := slf[key].(float64)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetBool 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetBool(key any) bool {
|
||||
v, _ := slf[key].(bool)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetTime 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetTime(key any) time.Time {
|
||||
v, _ := slf[key].(time.Time)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetDuration 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetDuration(key any) time.Duration {
|
||||
v, _ := slf[key].(time.Duration)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetByte 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetByte(key any) byte {
|
||||
v, _ := slf[key].(byte)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetBytes 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetBytes(key any) []byte {
|
||||
v, _ := slf[key].([]byte)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetRune 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetRune(key any) rune {
|
||||
v, _ := slf[key].(rune)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetRunes 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetRunes(key any) []rune {
|
||||
v, _ := slf[key].([]rune)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetAny 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
|
||||
func (slf Condition) GetAny(key any) any {
|
||||
return slf[key]
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package task
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrTaskNotFinish 任务未完成
|
||||
ErrTaskNotFinish = errors.New("task not finish")
|
||||
// ErrTaskRewardReceived 任务奖励已领取
|
||||
ErrTaskRewardReceived = errors.New("task reward received")
|
||||
// ErrTaskNotStart 任务未开始
|
||||
ErrTaskNotStart = errors.New("task not start")
|
||||
// ErrTaskFail 任务失败
|
||||
ErrTaskFail = errors.New("task fail")
|
||||
)
|
|
@ -1,35 +1,77 @@
|
|||
package task
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type (
|
||||
RefreshTaskCountEvent func(taskType int, increase int64)
|
||||
RefreshTaskChildCountEvent func(taskType int, key any, increase int64)
|
||||
RefreshTaskCounterEventHandler[Trigger any] func(taskType string, trigger Trigger, count int64) // 刷新任务计数器事件处理函数
|
||||
RefreshTaskConditionEventHandler[Trigger any] func(taskType string, trigger Trigger, condition Condition) // 刷新任务条件事件处理函数
|
||||
)
|
||||
|
||||
var (
|
||||
refreshTaskCountEventHandles = make(map[int]RefreshTaskCountEvent)
|
||||
refreshTaskChildCountEventHandles = make(map[int]RefreshTaskChildCountEvent)
|
||||
refreshTaskCounterEventHandlers = make(map[string][]struct {
|
||||
t reflect.Type
|
||||
h func(taskType string, trigger any, count int64)
|
||||
})
|
||||
refreshTaskConditionEventHandlers = make(map[string][]struct {
|
||||
t reflect.Type
|
||||
h func(taskType string, trigger any, condition Condition)
|
||||
})
|
||||
)
|
||||
|
||||
// RegRefreshTaskCount 注册任务计数刷新事件
|
||||
func RegRefreshTaskCount(taskType int, handler RefreshTaskCountEvent) {
|
||||
refreshTaskCountEventHandles[taskType] = handler
|
||||
// RegisterRefreshTaskCounterEvent 注册特定任务类型的刷新任务计数器事件处理函数
|
||||
func RegisterRefreshTaskCounterEvent[Trigger any](taskType string, handler RefreshTaskCounterEventHandler[Trigger]) {
|
||||
if refreshTaskCounterEventHandlers == nil {
|
||||
refreshTaskCounterEventHandlers = make(map[string][]struct {
|
||||
t reflect.Type
|
||||
h func(taskType string, trigger any, count int64)
|
||||
})
|
||||
}
|
||||
refreshTaskCounterEventHandlers[taskType] = append(refreshTaskCounterEventHandlers[taskType], struct {
|
||||
t reflect.Type
|
||||
h func(taskType string, trigger any, count int64)
|
||||
}{reflect.TypeOf(handler).In(1), func(taskType string, trigger any, count int64) {
|
||||
handler(taskType, trigger.(Trigger), count)
|
||||
}})
|
||||
}
|
||||
|
||||
// OnRefreshTaskCount 触发任务计数刷新事件
|
||||
func OnRefreshTaskCount(taskType int, increase int64) {
|
||||
if handler, ok := refreshTaskCountEventHandles[taskType]; ok {
|
||||
handler(taskType, increase)
|
||||
// OnRefreshTaskCounterEvent 触发特定任务类型的刷新任务计数器事件
|
||||
func OnRefreshTaskCounterEvent(taskType string, trigger any, count int64) {
|
||||
if handlers, exist := refreshTaskCounterEventHandlers[taskType]; exist {
|
||||
for _, handler := range handlers {
|
||||
if !reflect.TypeOf(trigger).AssignableTo(handler.t) {
|
||||
continue
|
||||
}
|
||||
handler.h(taskType, trigger, count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RegRefreshTaskChildCount 注册任务子计数刷新事件
|
||||
func RegRefreshTaskChildCount(taskType int, handler RefreshTaskChildCountEvent) {
|
||||
refreshTaskChildCountEventHandles[taskType] = handler
|
||||
// RegisterRefreshTaskConditionEvent 注册特定任务类型的刷新任务条件事件处理函数
|
||||
func RegisterRefreshTaskConditionEvent[Trigger any](taskType string, handler RefreshTaskConditionEventHandler[Trigger]) {
|
||||
if refreshTaskConditionEventHandlers == nil {
|
||||
refreshTaskConditionEventHandlers = make(map[string][]struct {
|
||||
t reflect.Type
|
||||
h func(taskType string, trigger any, condition Condition)
|
||||
})
|
||||
}
|
||||
refreshTaskConditionEventHandlers[taskType] = append(refreshTaskConditionEventHandlers[taskType], struct {
|
||||
t reflect.Type
|
||||
h func(taskType string, trigger any, condition Condition)
|
||||
}{reflect.TypeOf(handler).In(1), func(taskType string, trigger any, condition Condition) {
|
||||
handler(taskType, trigger.(Trigger), condition)
|
||||
}})
|
||||
}
|
||||
|
||||
// OnRefreshTaskChildCount 触发任务子计数刷新事件
|
||||
func OnRefreshTaskChildCount(taskType int, key any, increase int64) {
|
||||
if handler, ok := refreshTaskChildCountEventHandles[taskType]; ok {
|
||||
handler(taskType, key, increase)
|
||||
// OnRefreshTaskConditionEvent 触发特定任务类型的刷新任务条件事件
|
||||
func OnRefreshTaskConditionEvent(taskType string, trigger any, condition Condition) {
|
||||
if handlers, exist := refreshTaskConditionEventHandlers[taskType]; exist {
|
||||
for _, handler := range handlers {
|
||||
if !reflect.TypeOf(trigger).AssignableTo(handler.t) {
|
||||
continue
|
||||
}
|
||||
handler.h(taskType, trigger, condition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,85 +1,82 @@
|
|||
package task
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/offset"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Option 任务选项
|
||||
type Option func(task *Task)
|
||||
|
||||
// WithChildCount 通过初始化子计数的方式创建任务
|
||||
func WithChildCount(key any, childCount int64) Option {
|
||||
// WithType 设置任务类型
|
||||
func WithType(taskType string) Option {
|
||||
return func(task *Task) {
|
||||
if task.childCount == nil {
|
||||
task.childCount = make(map[any]int64)
|
||||
task.Type = taskType
|
||||
}
|
||||
}
|
||||
|
||||
// WithCondition 设置任务完成条件,当满足条件时,任务状态为完成
|
||||
// - 任务条件值需要变更时可通过 Task.AssignConditionValueAndRefresh 方法变更
|
||||
// - 当多次设置该选项时,后面的设置会覆盖之前的设置
|
||||
func WithCondition(condition Condition) Option {
|
||||
return func(task *Task) {
|
||||
if condition == nil {
|
||||
return
|
||||
}
|
||||
if task.childCondition == nil {
|
||||
task.childCondition = make(map[any]int64)
|
||||
if task.Cond == nil {
|
||||
task.Cond = condition
|
||||
return
|
||||
}
|
||||
task.childCount[key] = childCount
|
||||
}
|
||||
}
|
||||
|
||||
// WithChild 通过指定子计数的方式创建任务
|
||||
// - 只有当子计数与主计数均达到条件时,任务才会完成
|
||||
// - 通常用于多条件的任务
|
||||
func WithChild(key any, childCondition int64) Option {
|
||||
return func(task *Task) {
|
||||
if task.childCount == nil {
|
||||
task.childCount = make(map[any]int64)
|
||||
}
|
||||
if task.childCondition == nil {
|
||||
task.childCondition = make(map[any]int64)
|
||||
}
|
||||
task.childCondition[key] = childCondition
|
||||
}
|
||||
}
|
||||
|
||||
// WithDisableNotStartGetReward 禁止未开始的任务领取奖励
|
||||
func WithDisableNotStartGetReward() Option {
|
||||
return func(task *Task) {
|
||||
task.disableNotStartGetReward = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithCount 通过初始化计数的方式创建任务
|
||||
func WithCount(count int64) Option {
|
||||
return func(task *Task) {
|
||||
task.SetCount(count)
|
||||
}
|
||||
}
|
||||
|
||||
// WithStartTime 通过指定开始时间的方式创建任务
|
||||
// - 只有当时间在开始时间之后,任务才会开始计数
|
||||
func WithStartTime(startTime time.Time) Option {
|
||||
return func(task *Task) {
|
||||
task.start = startTime
|
||||
}
|
||||
}
|
||||
|
||||
// WithOffsetTime 通过指定偏移时间的方式创建任务
|
||||
func WithOffsetTime(offset *offset.Time) Option {
|
||||
return func(task *Task) {
|
||||
task.offset = offset
|
||||
}
|
||||
}
|
||||
|
||||
// WithLimitedTime 通过限时的方式创建任务
|
||||
func WithLimitedTime(limitTime time.Duration) Option {
|
||||
return func(task *Task) {
|
||||
task.limitTime = limitTime
|
||||
}
|
||||
}
|
||||
|
||||
// WithFront 通过指定任务前置任务的方式创建任务
|
||||
// - 当前置任务未完成时,当前任务不会开始计数
|
||||
func WithFront(fronts ...*Task) Option {
|
||||
return func(task *Task) {
|
||||
if task.fronts == nil {
|
||||
task.fronts = make(map[int64]*Task)
|
||||
}
|
||||
for _, front := range fronts {
|
||||
task.fronts[front.GetID()] = front
|
||||
for k, v := range condition {
|
||||
task.Cond[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithCounter 设置任务计数器,当计数器达到要求时,任务状态为完成
|
||||
// - 一些场景下,任务计数器可能会溢出,此时可通过 WithOverflowCounter 设置可溢出的任务计数器
|
||||
// - 当多次设置该选项时,后面的设置会覆盖之前的设置
|
||||
// - 如果需要初始化计数器的值,可通过 initCount 参数设置
|
||||
func WithCounter(counter int64, initCount ...int64) Option {
|
||||
return func(task *Task) {
|
||||
task.Counter = counter
|
||||
if len(initCount) > 0 {
|
||||
task.CurrCount = initCount[0]
|
||||
if task.CurrCount < 0 {
|
||||
task.CurrCount = 0
|
||||
} else if task.CurrCount > task.Counter {
|
||||
task.CurrCount = task.Counter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithOverflowCounter 设置可溢出的任务计数器,当计数器达到要求时,任务状态为完成
|
||||
// - 当多次设置该选项时,后面的设置会覆盖之前的设置
|
||||
// - 如果需要初始化计数器的值,可通过 initCount 参数设置
|
||||
func WithOverflowCounter(counter int64, initCount ...int64) Option {
|
||||
return func(task *Task) {
|
||||
task.Counter = counter
|
||||
task.CurrOverflow = true
|
||||
if len(initCount) > 0 {
|
||||
task.CurrCount = initCount[0]
|
||||
if task.CurrCount < 0 {
|
||||
task.CurrCount = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithDeadline 设置任务截止时间,超过截至时间并且任务未完成时,任务状态为失败
|
||||
func WithDeadline(deadline time.Time) Option {
|
||||
return func(task *Task) {
|
||||
task.Deadline = deadline
|
||||
}
|
||||
}
|
||||
|
||||
// WithLimitedDuration 设置任务限时,超过限时时间并且任务未完成时,任务状态为失败
|
||||
func WithLimitedDuration(start time.Time, duration time.Duration) Option {
|
||||
return func(task *Task) {
|
||||
task.StartTime = start
|
||||
task.LimitedDuration = duration
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
package task
|
||||
|
||||
const (
|
||||
StateAccept State = iota + 1 // 已接受
|
||||
StateFinish // 已完成
|
||||
StateReward // 已领取
|
||||
StateFail // 已失败
|
||||
)
|
||||
|
||||
type State uint16
|
|
@ -0,0 +1,23 @@
|
|||
package task
|
||||
|
||||
const (
|
||||
StatusAccept Status = iota + 1 // 已接受
|
||||
StatusFailed // 已失败
|
||||
StatusComplete // 已完成
|
||||
StatusReward // 已领取奖励
|
||||
)
|
||||
|
||||
var (
|
||||
statusFormat = map[Status]string{
|
||||
StatusAccept: "Accept",
|
||||
StatusComplete: "Complete",
|
||||
StatusReward: "Reward",
|
||||
StatusFailed: "Failed",
|
||||
}
|
||||
)
|
||||
|
||||
type Status byte
|
||||
|
||||
func (slf Status) String() string {
|
||||
return statusFormat[slf]
|
||||
}
|
|
@ -1,207 +1,152 @@
|
|||
package task
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/hash"
|
||||
"github.com/kercylan98/minotaur/utils/offset"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewTask 创建任务
|
||||
func NewTask(id int64, taskType int, condition int64, options ...Option) *Task {
|
||||
task := &Task{
|
||||
id: id,
|
||||
taskType: taskType,
|
||||
condition: condition,
|
||||
state: StateAccept,
|
||||
}
|
||||
// NewTask 生成任务
|
||||
func NewTask(options ...Option) *Task {
|
||||
task := new(Task)
|
||||
for _, option := range options {
|
||||
option(task)
|
||||
}
|
||||
if task.start.IsZero() {
|
||||
if task.offset != nil {
|
||||
task.start = task.offset.Now()
|
||||
} else {
|
||||
task.start = time.Now()
|
||||
}
|
||||
}
|
||||
for key := range task.childCount {
|
||||
if !hash.Exist(task.childCondition, key) {
|
||||
delete(task.childCount, key)
|
||||
}
|
||||
}
|
||||
if task.count == task.condition {
|
||||
task.state = StateFinish
|
||||
}
|
||||
return task
|
||||
return task.refreshTaskStatus()
|
||||
}
|
||||
|
||||
// Task 通用任务数据结构
|
||||
// Task 是对任务信息进行描述和处理的结构体
|
||||
type Task struct {
|
||||
id int64 // 任务ID
|
||||
taskType int // 任务类型
|
||||
count int64 // 任务主计数
|
||||
condition int64 // 任务完成需要的计数条件
|
||||
childCount map[any]int64 // 任务子计数
|
||||
childCondition map[any]int64 // 任务子计数条件
|
||||
state State // 任务状态
|
||||
start time.Time // 任务开始时间
|
||||
limitTime time.Duration // 任务限时
|
||||
fronts map[int64]*Task // 任务前置任务
|
||||
disableNotStartGetReward bool // 禁止未开始的任务领取奖励
|
||||
|
||||
offset *offset.Time // 任务偏移时间
|
||||
Type string `json:"type,omitempty"` // 任务类型
|
||||
Status Status `json:"status,omitempty"` // 任务状态
|
||||
Cond Condition `json:"cond,omitempty"` // 任务条件
|
||||
CondValue map[any]any `json:"cond_value,omitempty"` // 任务条件值
|
||||
Counter int64 `json:"counter,omitempty"` // 任务要求计数器
|
||||
CurrCount int64 `json:"curr_count,omitempty"` // 任务当前计数
|
||||
CurrOverflow bool `json:"curr_overflow,omitempty"` // 任务当前计数是否允许溢出
|
||||
Deadline time.Time `json:"deadline,omitempty"` // 任务截止时间
|
||||
StartTime time.Time `json:"start_time,omitempty"` // 任务开始时间
|
||||
LimitedDuration time.Duration `json:"limited_duration,omitempty"` // 任务限时
|
||||
}
|
||||
|
||||
// GetID 获取任务ID
|
||||
func (slf *Task) GetID() int64 {
|
||||
return slf.id
|
||||
// IsComplete 判断任务是否已完成
|
||||
func (slf *Task) IsComplete() bool {
|
||||
return slf.Status == StatusComplete
|
||||
}
|
||||
|
||||
// GetType 获取任务类型
|
||||
func (slf *Task) GetType() int {
|
||||
return slf.taskType
|
||||
// IsFailed 判断任务是否已失败
|
||||
func (slf *Task) IsFailed() bool {
|
||||
return slf.Status == StatusFailed
|
||||
}
|
||||
|
||||
// Reset 重置任务
|
||||
func (slf *Task) Reset() {
|
||||
slf.count = 0
|
||||
slf.state = StateAccept
|
||||
for key := range slf.childCount {
|
||||
delete(slf.childCount, key)
|
||||
}
|
||||
}
|
||||
|
||||
// GetFronts 获取前置任务
|
||||
func (slf *Task) GetFronts() map[int64]*Task {
|
||||
return slf.fronts
|
||||
}
|
||||
|
||||
// GetFrontsWithState 获取特定状态的前置任务
|
||||
func (slf *Task) GetFrontsWithState(state State) map[int64]*Task {
|
||||
fronts := make(map[int64]*Task)
|
||||
for id, front := range slf.fronts {
|
||||
if front.GetState() == state {
|
||||
fronts[id] = front
|
||||
}
|
||||
}
|
||||
return fronts
|
||||
}
|
||||
|
||||
// FrontsIsFinish 判断前置任务是否完成
|
||||
func (slf *Task) FrontsIsFinish() bool {
|
||||
for _, front := range slf.fronts {
|
||||
state := front.GetState()
|
||||
if state == StateAccept || state == StateFail {
|
||||
return false
|
||||
}
|
||||
// IsReward 判断任务是否已领取奖励
|
||||
func (slf *Task) IsReward() bool {
|
||||
return slf.Status == StatusReward
|
||||
}
|
||||
|
||||
// ReceiveReward 领取任务奖励,当任务状态为已完成时,才能领取奖励,此时返回 true,并且任务状态变更为已领取奖励
|
||||
func (slf *Task) ReceiveReward() bool {
|
||||
if slf.Status != StatusComplete {
|
||||
return false
|
||||
}
|
||||
slf.Status = StatusReward
|
||||
return true
|
||||
}
|
||||
|
||||
// GetReward 获取任务奖励
|
||||
// - 当任务状态为 StateFinish 时,调用 rewardHandle 函数
|
||||
// - 当任务状态不为 StateFinish 或奖励函数发生错误时,返回错误
|
||||
func (slf *Task) GetReward(rewardHandle func() error) error {
|
||||
if !slf.IsStart() {
|
||||
return ErrTaskNotStart
|
||||
// IncrementCounter 增加计数器的值,当 incr 为负数时,计数器的值不会发生变化
|
||||
// - 如果需要溢出计数器,可通过 WithOverflowCounter 设置可溢出的任务计数器
|
||||
func (slf *Task) IncrementCounter(incr int64) *Task {
|
||||
if incr < 0 {
|
||||
return slf
|
||||
}
|
||||
switch slf.GetState() {
|
||||
case StateAccept:
|
||||
return ErrTaskNotFinish
|
||||
case StateReward:
|
||||
return ErrTaskRewardReceived
|
||||
case StateFail:
|
||||
return ErrTaskFail
|
||||
slf.CurrCount += incr
|
||||
if !slf.CurrOverflow && slf.CurrCount > slf.Counter {
|
||||
slf.CurrCount = slf.Counter
|
||||
}
|
||||
if err := rewardHandle(); err != nil {
|
||||
return err
|
||||
}
|
||||
slf.state = StateReward
|
||||
return nil
|
||||
return slf.refreshTaskStatus()
|
||||
}
|
||||
|
||||
// GetState 获取任务状态
|
||||
func (slf *Task) GetState() State {
|
||||
return slf.state
|
||||
}
|
||||
|
||||
// IsStart 判断任务是否开始
|
||||
func (slf *Task) IsStart() bool {
|
||||
var current time.Time
|
||||
if slf.offset != nil {
|
||||
current = slf.offset.Now()
|
||||
} else {
|
||||
current = time.Now()
|
||||
// DecrementCounter 减少计数器的值,当 decr 为负数时,计数器的值不会发生变化
|
||||
func (slf *Task) DecrementCounter(decr int64) *Task {
|
||||
if decr < 0 {
|
||||
return slf
|
||||
}
|
||||
if current.Before(slf.start) {
|
||||
return false
|
||||
} else if slf.limitTime > 0 && current.Sub(slf.start) >= slf.limitTime {
|
||||
return false
|
||||
slf.CurrCount -= decr
|
||||
if slf.CurrCount < 0 {
|
||||
slf.CurrCount = 0
|
||||
}
|
||||
return true
|
||||
return slf.refreshTaskStatus()
|
||||
}
|
||||
|
||||
// SetCount 设置计数
|
||||
func (slf *Task) SetCount(count int64) {
|
||||
if !slf.IsStart() || !slf.FrontsIsFinish() {
|
||||
return
|
||||
// AssignConditionValueAndRefresh 分配条件值并刷新任务状态
|
||||
func (slf *Task) AssignConditionValueAndRefresh(key, value any) *Task {
|
||||
if slf.Cond == nil {
|
||||
return slf
|
||||
}
|
||||
slf.count = count
|
||||
if slf.count >= slf.condition {
|
||||
slf.count = slf.condition
|
||||
} else if slf.count < 0 {
|
||||
slf.count = 0
|
||||
if _, exist := slf.Cond[key]; !exist {
|
||||
return slf
|
||||
}
|
||||
slf.refreshState()
|
||||
}
|
||||
|
||||
// AddCount 增加计数
|
||||
func (slf *Task) AddCount(count int64) {
|
||||
slf.SetCount(slf.count + count)
|
||||
}
|
||||
|
||||
// GetCount 获取计数
|
||||
func (slf *Task) GetCount() int64 {
|
||||
return slf.count
|
||||
}
|
||||
|
||||
// GetCondition 获取计数条件
|
||||
func (slf *Task) GetCondition() int64 {
|
||||
return slf.condition
|
||||
}
|
||||
|
||||
// SetChildCount 设置子计数
|
||||
func (slf *Task) SetChildCount(key any, count int64) {
|
||||
if !slf.IsStart() || !slf.FrontsIsFinish() || !hash.Exist(slf.childCondition, key) {
|
||||
return
|
||||
if slf.CondValue == nil {
|
||||
slf.CondValue = make(map[any]any)
|
||||
}
|
||||
if condition := slf.childCondition[key]; count > condition {
|
||||
count = condition
|
||||
} else if count < 0 {
|
||||
count = 0
|
||||
}
|
||||
slf.childCount[key] = count
|
||||
slf.refreshState()
|
||||
OnRefreshTaskCount(slf.taskType, count)
|
||||
slf.CondValue[key] = value
|
||||
return slf.refreshTaskStatus()
|
||||
}
|
||||
|
||||
// AddChildCount 增加子计数
|
||||
func (slf *Task) AddChildCount(key any, count int64) {
|
||||
slf.SetChildCount(key, slf.childCount[key]+count)
|
||||
OnRefreshTaskChildCount(slf.taskType, key, count)
|
||||
// AssignConditionValueAndRefreshByCondition 分配条件值并刷新任务状态
|
||||
func (slf *Task) AssignConditionValueAndRefreshByCondition(condition Condition) *Task {
|
||||
if slf.Cond == nil {
|
||||
return slf
|
||||
}
|
||||
if slf.CondValue == nil {
|
||||
slf.CondValue = make(map[any]any)
|
||||
}
|
||||
for k, v := range condition {
|
||||
if _, exist := slf.Cond[k]; !exist {
|
||||
continue
|
||||
}
|
||||
slf.CondValue[k] = v
|
||||
}
|
||||
return slf.refreshTaskStatus()
|
||||
}
|
||||
|
||||
// refreshState 刷新任务状态
|
||||
func (slf *Task) refreshState() {
|
||||
slf.state = StateFinish
|
||||
if slf.count != slf.condition {
|
||||
slf.state = StateAccept
|
||||
return
|
||||
// ResetStatus 重置任务状态
|
||||
// - 该函数会将任务状态重置为已接受状态后,再刷新任务状态
|
||||
// - 当任务条件变更,例如任务计数要求为 10,已经完成的情况下,将任务计数要求变更为 5 或 20,此时任务状态由于是已完成或已领取状态,不会自动刷新,需要调用该函数刷新任务状态
|
||||
func (slf *Task) ResetStatus() *Task {
|
||||
slf.Status = StatusAccept
|
||||
return slf.refreshTaskStatus()
|
||||
}
|
||||
|
||||
// refreshTaskStatus 刷新任务状态
|
||||
func (slf *Task) refreshTaskStatus() *Task {
|
||||
curr := time.Now()
|
||||
if (!slf.StartTime.IsZero() && curr.Before(slf.StartTime)) || (!slf.Deadline.IsZero() && curr.After(slf.Deadline)) || slf.Status >= StatusComplete {
|
||||
return slf
|
||||
}
|
||||
for key, condition := range slf.childCondition {
|
||||
if slf.childCount[key] != condition {
|
||||
slf.state = StateAccept
|
||||
return
|
||||
slf.Status = StatusComplete
|
||||
|
||||
if slf.Counter > 0 && slf.CurrCount < slf.Counter {
|
||||
slf.Status = StatusAccept
|
||||
return slf
|
||||
}
|
||||
if slf.Cond != nil {
|
||||
for k, v := range slf.Cond {
|
||||
if v != slf.CondValue[k] {
|
||||
slf.Status = StatusAccept
|
||||
return slf
|
||||
}
|
||||
}
|
||||
}
|
||||
if !slf.Deadline.IsZero() && slf.Status == StatusAccept {
|
||||
if slf.Deadline.After(curr) {
|
||||
slf.Status = StatusFailed
|
||||
return slf
|
||||
}
|
||||
}
|
||||
if slf.LimitedDuration > 0 && slf.Status == StatusAccept {
|
||||
if curr.Sub(slf.StartTime) > slf.LimitedDuration {
|
||||
slf.Status = StatusFailed
|
||||
return slf
|
||||
}
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package task
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Player struct {
|
||||
tasks map[string][]*Task
|
||||
}
|
||||
|
||||
type Monster struct {
|
||||
}
|
||||
|
||||
func TestCond(t *testing.T) {
|
||||
task := NewTask(WithType("T"), WithCounter(5), WithCondition(Cond("N", 5).Cond("M", 10)))
|
||||
task.AssignConditionValueAndRefresh("N", 5)
|
||||
task.AssignConditionValueAndRefresh("M", 10)
|
||||
|
||||
RegisterRefreshTaskCounterEvent[*Player](task.Type, func(taskType string, trigger *Player, count int64) {
|
||||
fmt.Println("Player", count)
|
||||
for _, t := range trigger.tasks[taskType] {
|
||||
fmt.Println(t.CurrCount, t.IncrementCounter(count).Status)
|
||||
}
|
||||
})
|
||||
|
||||
RegisterRefreshTaskConditionEvent[*Player](task.Type, func(taskType string, trigger *Player, condition Condition) {
|
||||
fmt.Println("Player", condition)
|
||||
for _, t := range trigger.tasks[taskType] {
|
||||
fmt.Println(t.CurrCount, t.AssignConditionValueAndRefresh("N", 5).Status)
|
||||
}
|
||||
})
|
||||
|
||||
RegisterRefreshTaskCounterEvent[*Monster](task.Type, func(taskType string, trigger *Monster, count int64) {
|
||||
fmt.Println("Monster", count)
|
||||
})
|
||||
|
||||
player := &Player{
|
||||
tasks: map[string][]*Task{
|
||||
task.Type: []*Task{task},
|
||||
},
|
||||
}
|
||||
OnRefreshTaskCounterEvent(task.Type, player, 1)
|
||||
OnRefreshTaskCounterEvent(task.Type, player, 2)
|
||||
OnRefreshTaskCounterEvent(task.Type, player, 3)
|
||||
OnRefreshTaskCounterEvent(task.Type, new(Monster), 3)
|
||||
|
||||
}
|
Loading…
Reference in New Issue