ZeroBot-Plugin/plugin/warframeapi/world.go

102 lines
2.4 KiB
Go

package warframeapi
import (
"strings"
"sync"
"sync/atomic"
"time"
"github.com/davidscholberg/go-durationfmt"
)
// 游戏时间模拟
type timezone struct {
sync.RWMutex `json:"-"`
Name string `json:"name"` // 时间名称
NextTime time.Time `json:"time"` // 下次更新时间
IsDay bool `json:"status"` // 状态
DayDesc string `json:"true_des"` // 状态说明
NightDesc string `json:"false_des"` // 状态说明
DayLen int `json:"day"` // 白天时长
NightLen int `json:"night"` // 夜间时长
}
type world struct {
w [3]*timezone
hassync uintptr
}
var (
gameWorld world
)
// String 根据传入的世界编号,获取对应的游戏时间文本
func (t *timezone) String() string {
t.RLock()
defer t.RUnlock()
sb := strings.Builder{}
sb.WriteString("平原时间: ")
if t.IsDay {
sb.WriteString(t.DayDesc)
} else {
sb.WriteString(t.NightDesc)
}
sb.WriteString(", ")
sb.WriteString("下次更新: ")
d := time.Until(t.NextTime)
durStr, _ := durationfmt.Format(d, "%m分%s秒后")
sb.WriteString(durStr)
return sb.String()
}
func (w *world) hasSync() bool {
return atomic.LoadUintptr(&w.hassync) != 0
}
func (w *world) setsync() bool {
return atomic.CompareAndSwapUintptr(&w.hassync, 0, 1)
}
func (w *world) resetsync() bool {
return atomic.CompareAndSwapUintptr(&w.hassync, 1, 0)
}
// 根据API返回内容修正游戏时间
func (w *world) refresh(api *wfapi) {
for _, t := range w.w {
t.Lock()
}
w.w[0].NextTime = api.CetusCycle.Expiry.Local()
w.w[0].IsDay = api.CetusCycle.IsDay
w.w[1].NextTime = api.VallisCycle.Expiry.Local()
w.w[1].IsDay = api.VallisCycle.IsWarm
w.w[2].NextTime = api.CambionCycle.Expiry.Local()
w.w[2].IsDay = api.CambionCycle.Active == "fass"
}
// 游戏时间更新
func (w *world) update() {
if !w.hasSync() {
return
}
for _, t := range w.w {
t.Lock()
// 当前时间对比下一次游戏状态更新时间,看看还剩多少秒
nt := time.Until(t.NextTime).Seconds()
// 已经过了游戏时间状态更新时间
if nt < 0 {
// 更新游戏状态,如果是白天就切换到晚上,反之亦然
if t.IsDay {
// 计算下次的晚上更新时间
t.NextTime = t.NextTime.Add(time.Duration(t.NightLen) * time.Second)
} else {
// 计算下次的白天更新时间
t.NextTime = t.NextTime.Add(time.Duration(t.DayLen) * time.Second)
}
}
t.Unlock()
}
}