refactor: 任务 task 包重构

This commit is contained in:
kercylan98 2023-07-11 13:30:44 +08:00
parent 8368fe0770
commit a23e48b087
6 changed files with 289 additions and 66 deletions

14
game/task/errors.go Normal file
View File

@ -0,0 +1,14 @@
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")
)

View File

@ -1,32 +1,35 @@
package task package task
type ( type (
TaskDoneEventHandle func(eventId int64, task *Task) RefreshTaskCountEvent func(taskType int, increase int64)
RefreshTaskChildCountEvent func(taskType int, key any, increase int64)
) )
var taskDoneEventHandles = make(map[int64]map[int64]TaskDoneEventHandle) var (
refreshTaskCountEventHandles = make(map[int]RefreshTaskCountEvent)
refreshTaskChildCountEventHandles = make(map[int]RefreshTaskChildCountEvent)
)
// RegTaskDoneEvent 注册任务完成事件 // RegRefreshTaskCount 注册任务计数刷新事件
func RegTaskDoneEvent(id int64, eventId int64, handle TaskDoneEventHandle) { func RegRefreshTaskCount(taskType int, handler RefreshTaskCountEvent) {
events, exist := taskDoneEventHandles[id] refreshTaskCountEventHandles[taskType] = handler
if !exist {
events = map[int64]TaskDoneEventHandle{}
taskDoneEventHandles[id] = events
}
events[eventId] = handle
} }
// UnRegTaskDoneEvent 取消注册任务完成事件 // OnRefreshTaskCount 触发任务计数刷新事件
func UnRegTaskDoneEvent(id int64, eventId int64) { func OnRefreshTaskCount(taskType int, increase int64) {
events, exist := taskDoneEventHandles[id] if handler, ok := refreshTaskCountEventHandles[taskType]; ok {
if exist { handler(taskType, increase)
delete(events, eventId)
} }
} }
// OnTaskDoneEvent 任务完成事件 // RegRefreshTaskChildCount 注册任务子计数刷新事件
func OnTaskDoneEvent(task *Task) { func RegRefreshTaskChildCount(taskType int, handler RefreshTaskChildCountEvent) {
for eventId, handle := range taskDoneEventHandles[task.id] { refreshTaskChildCountEventHandles[taskType] = handler
handle(eventId, task) }
// OnRefreshTaskChildCount 触发任务子计数刷新事件
func OnRefreshTaskChildCount(taskType int, key any, increase int64) {
if handler, ok := refreshTaskChildCountEventHandles[taskType]; ok {
handler(taskType, key, increase)
} }
} }

View File

@ -1,17 +1,85 @@
package task package task
import (
"github.com/kercylan98/minotaur/utils/offset"
"time"
)
type Option func(task *Task) type Option func(task *Task)
// WithInitCount 通过初始化计数的方式创建任务 // WithChildCount 通过初始化子计数的方式创建任务
func WithInitCount(count int) Option { func WithChildCount(key any, childCount int64) Option {
return func(task *Task) { return func(task *Task) {
task.count = count if task.childCount == nil {
task.childCount = make(map[any]int64)
}
if task.childCondition == nil {
task.childCondition = make(map[any]int64)
}
task.childCount[key] = childCount
} }
} }
// WithDone 通过指定任务完成计数的方式创建任务 // WithChild 通过指定子计数的方式创建任务
func WithDone(done int) Option { // - 只有当子计数与主计数均达到条件时,任务才会完成
// - 通常用于多条件的任务
func WithChild(key any, childCondition int64) Option {
return func(task *Task) { return func(task *Task) {
task.done = done 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
}
} }
} }

View File

@ -1,10 +1,10 @@
package task package task
const ( const (
StateDoing State = iota // 进行中 StateAccept State = iota // 已接受
StateDone // 已完成 StateFinish // 已完成
StateReward // 已领取 StateReward // 已领取
StateFail // 已失败
) )
// State 任务状态 type State uint16
type State byte

View File

@ -1,67 +1,204 @@
package task package task
// NewTask 新建任务 import (
func NewTask(id int64, options ...Option) *Task { "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{ task := &Task{
id: id, id: id,
condition: condition,
state: StateAccept,
} }
for _, option := range options { for _, option := range options {
option(task) option(task)
} }
if task.count > task.done { if task.start.IsZero() {
task.count = task.done 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
} }
task.Add(0)
return task return task
} }
// Task 通用任务数据结构
type Task struct { type Task struct {
id int64 // 任务ID id int64 // 任务ID
count int // 任务计数 taskType int // 任务类型
done int // 任务完成计数 count int64 // 任务主计数
reward bool // 是否已领取奖励 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 // 任务偏移时间
}
// GetID 获取任务ID
func (slf *Task) GetID() int64 {
return slf.id
}
// GetType 获取任务类型
func (slf *Task) GetType() int {
return slf.taskType
} }
// Reset 重置任务 // Reset 重置任务
func (slf *Task) Reset() { func (slf *Task) Reset() {
slf.count = 0 slf.count = 0
slf.reward = false slf.state = StateAccept
switch slf.GetState() { for key := range slf.childCount {
case StateDone: delete(slf.childCount, key)
OnTaskDoneEvent(slf)
} }
} }
// Add 增加任务计数 // GetFronts 获取前置任务
func (slf *Task) Add(count int) { func (slf *Task) GetFronts() map[int64]*Task {
if count != 0 { return slf.fronts
slf.count += count }
if slf.count < 0 {
slf.count = 0 // GetFrontsWithState 获取特定状态的前置任务
} else if slf.count > slf.done { func (slf *Task) GetFrontsWithState(state State) map[int64]*Task {
slf.count = slf.done fronts := make(map[int64]*Task)
for id, front := range slf.fronts {
if front.GetState() == state {
fronts[id] = front
} }
} }
switch slf.GetState() { return fronts
case StateDone: }
OnTaskDoneEvent(slf)
// FrontsIsFinish 判断前置任务是否完成
func (slf *Task) FrontsIsFinish() bool {
for _, front := range slf.fronts {
state := front.GetState()
if state == StateAccept || state == StateFail {
return false
}
} }
return true
}
// GetReward 获取任务奖励
// - 当任务状态为 StateFinish 时,调用 rewardHandle 函数
// - 当任务状态不为 StateFinish 或奖励函数发生错误时,返回错误
func (slf *Task) GetReward(rewardHandle func() error) error {
if !slf.IsStart() {
return ErrTaskNotStart
}
switch slf.GetState() {
case StateAccept:
return ErrTaskNotFinish
case StateReward:
return ErrTaskRewardReceived
case StateFail:
return ErrTaskFail
}
if err := rewardHandle(); err != nil {
return err
}
slf.state = StateReward
return nil
} }
// GetState 获取任务状态 // GetState 获取任务状态
func (slf *Task) GetState() State { func (slf *Task) GetState() State {
if slf.count >= slf.done { return slf.state
if slf.reward {
return StateReward
}
return StateDone
}
return StateDoing
} }
// Reward 返回是否领取过奖励,并且设置任务为领取过奖励的状态 // IsStart 判断任务是否开始
func (slf *Task) Reward() bool { func (slf *Task) IsStart() bool {
reward := slf.reward var current time.Time
slf.reward = true if slf.offset != nil {
return reward current = slf.offset.Now()
} else {
current = time.Now()
}
if current.Before(slf.start) {
return false
} else if slf.limitTime > 0 && current.Sub(slf.start) >= slf.limitTime {
return false
}
return true
}
// SetCount 设置计数
func (slf *Task) SetCount(count int64) {
if !slf.IsStart() || !slf.FrontsIsFinish() {
return
}
slf.count = count
if slf.count >= slf.condition {
slf.count = slf.condition
} else if slf.count < 0 {
slf.count = 0
}
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 condition := slf.childCondition[key]; count > condition {
count = condition
} else if count < 0 {
count = 0
}
slf.childCount[key] = count
slf.refreshState()
}
// AddChildCount 增加子计数
func (slf *Task) AddChildCount(key any, count int64) {
slf.SetChildCount(key, slf.childCount[key]+count)
}
// refreshState 刷新任务状态
func (slf *Task) refreshState() {
slf.state = StateFinish
if slf.count != slf.condition {
slf.state = StateAccept
return
}
for key, condition := range slf.childCondition {
if slf.childCount[key] != condition {
slf.state = StateAccept
return
}
}
} }

View File

@ -8,6 +8,7 @@ import (
const ( const (
DefaultTolerance = 0.0001 // 默认误差范围 DefaultTolerance = 0.0001 // 默认误差范围
Zero = 0 // 零
) )
// GetDefaultTolerance 获取默认误差范围 // GetDefaultTolerance 获取默认误差范围