feat(common): 添加GlowFilter的Level字段

添加了GlowFilter结构体中的Level字段,用于表示等级信息,
对应JSON标签为"level,omitempty"

---

fix(utils): 修复concurrent_swiss_map中的panic处理

- 使用goroutine替代线程池来监听通道
- 添加panic恢复机制,当发生panic时记录错误日志
- 确保在异常情况下程序能够
This commit is contained in:
昔念
2026-01-25 23:17:46 +08:00
parent 4dd05726af
commit fa928c9a48
20 changed files with 156 additions and 210 deletions

View File

@@ -47,6 +47,7 @@ type GlowFilter struct {
// Knockout 是否挖空,默认 false
Knockout bool `json:"knockout,omitempty"`
ColorMatrixFilter [20]float32 `json:"matrix,omitempty"`
Level uint8 `json:"level,omitempty"` //等级
}
// ItemInfo

View File

@@ -277,14 +277,22 @@ func (m *CsMap[K, V]) produce(ctx context.Context, ch chan Tuple[K, V]) {
func (m *CsMap[K, V]) listen(f func(key K, value V) (stop bool), ch chan Tuple[K, V]) *sync.WaitGroup {
var wg sync.WaitGroup
wg.Add(1)
m.pool.Submit(func() {
go func() {
defer wg.Done()
defer func() {
if err := recover(); err != nil { // 恢复 panicerr 为 panic 错误值
// 1. 打印错误信息
cool.Logger.Error(context.TODO(), "panic 错误:", err)
}
}()
for t := range ch {
if stop := f(t.Key, t.Val); stop {
return
}
}
})
}()
return &wg
}

View File

@@ -45,11 +45,8 @@ func (h Controller) Login(data *user.MAIN_LOGIN_IN, c gnet.Conn) (result *user.L
currentPlayer.Info.UserID = data.Head.UserID
currentPlayer.Logintime = uint32(time.Now().Unix()) //保存时间戳
currentPlayer.CompleteLogin() //通知客户端登录成功
result = user.NewOutInfo(currentPlayer.Info) //设置登录消息
result = user.NewOutInfo() //设置登录消息
result.PlayerInfo = *currentPlayer.Info
defer space.GetSpace(currentPlayer.Info.MapID).EnterMap(currentPlayer)
return result, 0

View File

@@ -49,7 +49,11 @@ func (h Controller) PetFusion(data *pet.C2S_PetFusion, c *player.Player) (result
}
resid := int(service.NewPetFusionService().Data(Mcatchpetinfo.ID, Auxpetinfo.ID, Mcatchpetinfo.Level+Auxpetinfo.Level))
effect := int(service.NewPetFusionMaterialService().Data(data.Item1))
if effect == 0 {
return result, errorcode.ErrorCodes.ErrSpiritOrbNotExists
}
for _, v := range data.Item1 {
if c.Service.Item.CheakItem(v) == 0 {
return &pet.PetFusionInfo{}, 0
@@ -81,12 +85,6 @@ func (h Controller) PetFusion(data *pet.C2S_PetFusion, c *player.Player) (result
return &pet.PetFusionInfo{}, 0
}
effect := int(service.NewPetFusionMaterialService().Data(data.Item1))
if effect == 0 {
return &pet.PetFusionInfo{}, 0
}
dv1 := alpacadecimal.NewFromInt(2).Div(alpacadecimal.NewFromInt(3)).Mul(alpacadecimal.NewFromInt(int64(Mcatchpetinfo.Dv)))
dv2 := alpacadecimal.NewFromInt(1).Div(alpacadecimal.NewFromInt(3)).Mul(alpacadecimal.NewFromInt(int64(Auxpetinfo.Dv)))
dv := dv1.Add(dv2).Add(alpacadecimal.NewFromInt(1)).IntPart()

View File

@@ -8,7 +8,7 @@ import (
// 免疫瞬杀
type NewSel114 struct {
NewSel0
v *input.Effect
v []*input.Effect
}
func (e *NewSel114) TurnStart(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) {
@@ -17,20 +17,22 @@ func (e *NewSel114) TurnStart(fattack *action.SelectSkillAction, sattack *action
return
}
for _, v := range e.Ctx().Opp.Opp.Effects {
for _, v := range e.Ctx().Opp.Effects {
if v.ID().GetEffectType() == input.EffectType.NewSel && v.ID().Suffix() == 32 {
v.Alive()
e.v = &v
v.Alive(false)
e.v = append(e.v, &v)
}
}
}
func (e *NewSel114) TurnEnd() {
if e.v != nil {
e.Alive(true)
for _, v := range e.v {
if v != nil {
e.Alive(true)
}
}
}

View File

@@ -84,7 +84,7 @@ func (p *Player) GenMonster() {
}
if cool.Config.ServerInfo.IsVip != 0 { //测试服,百分百异色
p.OgreInfo.Data[i].RandSHiny()
p.OgreInfo.Data[i].FixSHiny()
}
if xmlres.PetMAP[int(p.OgreInfo.Data[i].Id)].CatchRate != 0 && grand.Meet(3, 1000) {
p.OgreInfo.Data[i].RandSHiny()

View File

@@ -46,6 +46,18 @@ type OgrePetInfo struct {
}
func (o *OgrePetInfo) RandSHiny() {
var co *data.GlowFilter
if o.Ext == 0 {
co = config.NewShinyService().RandShiny(o.Id)
}
if co != nil && len(o.ShinyInfo) == 0 {
o.ShinyInfo = append(o.ShinyInfo, *co)
}
}
func (o *OgrePetInfo) FixSHiny() {
var co *data.GlowFilter
if o.Ext == 0 {
@@ -222,27 +234,27 @@ func (p *Player) ItemAdd(ItemId, ItemCnt uint32) (result bool) {
}
func (player1 *Player) Kick(qtype int) {
if player1.IsLogin {
//取成功,否则创建
//player1.Save() //先保存数据再返回
head := common.NewTomeeHeader(1001, player1.Info.UserID)
head.Result = uint32(errorcode.ErrorCodes.ErrAccountLoggedInElsewhere)
if qtype == 1 {
head.Result = uint32(errorcode.ErrorCodes.ErrXinPlanSleepMode)
}
//实际上这里有个问题,会造成重复保存问题
//取成功,否则创建
//player1.Save() //先保存数据再返回
head := common.NewTomeeHeader(1001, player1.Info.UserID)
player1.SendPack(head.Pack(nil))
CloseChan := make(chan struct{})
player1.MainConn.CloseWithCallback(func(c gnet.Conn, err error) error {
close(CloseChan)
return nil
})
<-CloseChan
head.Result = uint32(errorcode.ErrorCodes.ErrAccountLoggedInElsewhere)
if qtype == 1 {
head.Result = uint32(errorcode.ErrorCodes.ErrXinPlanSleepMode)
}
//实际上这里有个问题,会造成重复保存问题
player1.SendPack(head.Pack(nil))
CloseChan := make(chan struct{})
player1.MainConn.CloseWithCallback(func(c gnet.Conn, err error) error {
close(CloseChan)
return nil
})
<-CloseChan
}
func (p *Player) Cheak(b error) {

View File

@@ -3,7 +3,7 @@ package player
import (
"blazing/common/data/share"
"blazing/cool"
"blazing/modules/player/model"
"fmt"
"blazing/logic/service/fight/info"
"blazing/logic/service/space"
@@ -13,6 +13,7 @@ import (
// Save 保存玩家数据
func (p *Player) Save() {
cool.CacheManager.Remove(context.TODO(), fmt.Sprintf("player:%d", p.Info.UserID))
if cool.Config.ServerInfo.IsVip != 0 {
cool.Logger.Info(context.TODO(), "测试服不保存玩家数据", p.Info.UserID)
@@ -57,10 +58,9 @@ func (p *Player) Save() {
p.MapNPC.Stop() //停止刷怪
p.IsLogin = false
Mainplayer.Delete(p.Info.UserID)
share.ShareManager.DeleteUserOnline(p.Info.UserID) //设置用户登录服务器
}
// 是否可以获得经验
@@ -73,47 +73,3 @@ func (p *Player) CanGetExp() bool {
return (uint32(time.Now().Unix()) - uint32(p.Logintime)) <= ttt
}
// CompleteLogin 标记登录完成并通知等待者
func (lw *Player) CompleteLogin() {
if lw.Info.MapID > 300 || lw.Info.MapID == 0 { //如果位于基地,就重置到传送仓
lw.Info.MapID = 1
}
if lw.IsNewPlayer() { //重置新手地图,放到机械仓
lw.Info.SetTask(4, model.Completed) //设置新手任务默认完成
lw.Info.MapID = 8
if len(lw.Info.PetList) == 0 {
//这个是添加后防止卡死
rr := lw.Service.Pet.PetInfo(0)
if len(rr) > 0 {
lw.Info.PetList = append(lw.Info.PetList, rr[0].Data)
}
}
}
if lw.Info.MaxPuniLv < 9 {
for i := 291; i < 299; i++ {
if lw.Info.GetTask(i) == model.Completed {
lw.Info.MaxPuniLv = uint32(i) - 290
}
}
}
lw.IsLogin = true
}
// 定义检查函数判断84-87索引中是否有任意一个元素不等于3
func (lw *Player) IsNewPlayer() bool {
// 遍历84到87的索引
for i := 85; i <= 88; i++ {
if lw.Info.GetTask(i) != model.Completed {
return true // 只要有一个不等于3就返回true
}
}
return false // 全部等于3则返回false
}

View File

@@ -41,10 +41,10 @@ type LoginMSInfo struct {
model.PlayerInfo
}
func NewOutInfo() *LoginMSInfo {
func NewOutInfo(info *model.PlayerInfo) *LoginMSInfo {
l := &LoginMSInfo{
PlayerInfo: model.NewPlayerInfo(),
PlayerInfo: *info,
}
return l

View File

@@ -10,6 +10,7 @@ import (
"blazing/modules/base/service"
config "blazing/modules/config/service"
dict "blazing/modules/dict/service"
blazing "blazing/modules/player/service"
playerservice "blazing/modules/player/service"
@@ -66,13 +67,8 @@ func (c *BaseSysUserController) GetSession(ctx context.Context, req *SessionReq)
res.IsReg = 1
}
if cool.Config.ServerInfo.IsDebug != 0 {
res.LoginAddr = "192.168.1.44" + ":" + cool.Config.LoginPort
} else {
res.LoginAddr = cool.Config.File.Domain + ":" + cool.Config.LoginPort
}
res.Server = config.NewServerService().GetPort()
res.PetID = dict.NewDictInfoService().GetShiny()
res.Server = config.NewServerService().GetPort(int(t1.Debug))
// share.ShareManager.DeleteSession(t1)
ser := playerservice.NewUserService(uint32(t1.ID))
kickErr := ser.Info.Kick(uint32(t1.ID))
@@ -91,11 +87,12 @@ func (c *BaseSysUserController) GetSession(ctx context.Context, req *SessionReq)
}
type SessionRes struct {
IsReg int `json:"isreg"`
UserID int `json:"userid"`
Session string `json:"session"`
LoginAddr string `json:"loginaddr"`
Server gdb.List `json:"server"`
IsReg int `json:"isreg"`
UserID int `json:"userid"`
Session string `json:"session"`
Server gdb.List `json:"server"`
PetID []int `json:"petid"`
}
type RegReq struct {

View File

@@ -58,11 +58,8 @@ func init() {
g.Server().BindHandler("/server/*", func(r *ghttp.Request) {
servert := new(ServerHandler)
id := gconv.Uint16(r.URL.Query().Get("id"))
servert.isinstall = gconv.Uint32(r.URL.Query().Get("isinstall"))
if servert.isinstall != 0 {
servert.ServerList = service.NewServerService().StartUPdate(id)
}
servert.ServerList = service.NewServerService().StartUPdate(id, int(servert.isinstall))
upgrader := gws.NewUpgrader(servert, &gws.ServerOption{

View File

@@ -197,93 +197,11 @@ else
command -v screen || { echo "❌ Screen安装失败"; exit 1; }
fi
#!/bin/bash
# 核心无任何可能阻塞的命令全程实时输出100%不卡住 + 彻底清理所有logic会话
set -euo pipefail
# ===== 仅需配置这1个变量 =====
SCREEN_NAME="logic"
# ===== 颜色输出函数(确保能看到输出)=====
red() { echo -e "\033[31m[$(date +%H:%M:%S)] $1\033[0m"; }
green() { echo -e "\033[32m[$(date +%H:%M:%S)] $1\033[0m"; }
yellow() { echo -e "\033[33m[$(date +%H:%M:%S)] $1\033[0m"; }
# ===== 新增彻底清理screen会话核心修复=====
clean_screen_sessions() {
local sess_id=$1
# 1. 先优雅关闭screen会话
screen -S "${sess_id}" -X quit >/dev/null 2>&1 || true
sleep 0.3
# 2. 提取会话PID并强制杀死
local sess_pid=$(echo "${sess_id}" | cut -d. -f1)
if [ -n "${sess_pid}" ]; then
kill -9 "${sess_pid}" >/dev/null 2>&1 || true
# 3. 杀死该PID的所有子进程
pkill -9 -P "${sess_pid}" >/dev/null 2>&1 || true
fi
}
# ===== 强制关闭所有阻塞的后台进程(先清场)=====
green "【步骤1/5】清理脚本自身可能的阻塞进程"
pkill -f "screen_clean_*" >/dev/null 2>&1 || true
pkill -9 -f "pgrep -f SCREEN -S ${SCREEN_NAME}" >/dev/null 2>&1 || true
# ===== 非阻塞查找进程+会话关键延长超时到1秒查更全=====
green "【步骤2/5】查找${SCREEN_NAME}相关进程/会话(非阻塞)"
# 先查screen会话ID1秒超时避免漏查
SCREEN_SESS=$(timeout 1 screen -ls 2>/dev/null | grep -E "[0-9]+\\.${SCREEN_NAME}" | grep -v "Dead" | awk '{print $1}' || true)
# 再查进程PID
SCREEN_PIDS=$(timeout 1 pgrep -f "SCREEN -S ${SCREEN_NAME}" | grep -v $$ || true)
# 合并需要清理的目标
if [ -z "${SCREEN_SESS}" ] && [ -z "${SCREEN_PIDS}" ]; then
green "✅ 未找到${SCREEN_NAME}相关进程/会话,无需清理"
else
yellow "⚠️ 找到${SCREEN_NAME}会话:${SCREEN_SESS:-无}"
yellow "⚠️ 找到${SCREEN_NAME}进程:${SCREEN_PIDS:-无}"
# ===== 非阻塞强制清理(先清会话,再清进程)=====
green "【步骤3/5】强制清理${SCREEN_NAME}进程及会话"
# 1. 清理所有screen会话
if [ -n "${SCREEN_SESS}" ]; then
for sess in ${SCREEN_SESS}; do
yellow "🔧 清理会话:${sess}"
clean_screen_sessions "${sess}"
done
fi
# 2. 清理剩余进程(兜底)
if [ -n "${SCREEN_PIDS}" ]; then
for pid in ${SCREEN_PIDS}; do
yellow "🔧 清理进程:${pid}"
kill -9 "${pid}" >/dev/null 2>&1 || true
pkill -9 -P "${pid}" >/dev/null 2>&1 || true
done
fi
# 短暂等待0.5秒,非阻塞)
sleep 0.5
# ===== 验证清理结果(查会话+进程,双重验证)=====
green "【步骤4/5】验证清理结果会话+进程双重检查)"
FINAL_SESS=$(timeout 1 screen -ls 2>/dev/null | grep -E "[0-9]+\\.${SCREEN_NAME}" | grep -v "Dead" || true)
FINAL_PIDS=$(timeout 1 pgrep -f "SCREEN -S ${SCREEN_NAME}" | grep -v $$ || true)
if [ -z "${FINAL_SESS}" ] && [ -z "${FINAL_PIDS}" ]; then
green "✅ ${SCREEN_NAME}进程/会话已全部清理完成"
else
red "❌ 仍有残留:会话[${FINAL_SESS}] 进程[${FINAL_PIDS}],再次强制清理"
# 终极兜底:强制杀死所有相关进程
pkill -9 -f "${SCREEN_NAME}" >/dev/null 2>&1 || true
fi
fi
# ===== 最终收尾 =====
green "【步骤5/5】${SCREEN_NAME}会话清理流程结束"
green "✅ 自动化部署后续流程可正常执行"
# ===== 准备下载目录 =====
@@ -311,10 +229,8 @@ echo "下载链接:%s{file_url}"
echo "目标路径:%s{exe_path}"
# 删除旧文件(关键修复:这里要判断目标路径,不是下载链接)
if [ -f "%s{exe_path}" ]; then
echo "删除旧文件:%s{exe_path}"
rm -f "%s{exe_path}"
fi
echo "删除旧文件:%s{exe_path}"
rm -f "%s{exe_path}"
echo "开始下载..."
DOWNLOAD_SUCCESS=0

View File

@@ -98,6 +98,8 @@ type GroupAttributes struct {
IsHidden int `json:"isHidden"`
}
var bbsurl = "http://43.248.3.21:45632"
// GetUserInfo 输入用户名和密码,返回用户信息结构体
func GetUserInfo(username, password string) (*UserResponse, error) {
// 创建带 Cookie 存储的 HTTP 客户端
@@ -108,7 +110,7 @@ func GetUserInfo(username, password string) (*UserResponse, error) {
client := &http.Client{Jar: jar}
// 1. POST 获取 token
tokenURL := "http://bs.seersun.com/api/token"
tokenURL := bbsurl + "/api/token"
formData := url.Values{}
formData.Set("identification", username)
formData.Set("password", password)
@@ -141,7 +143,7 @@ func GetUserInfo(username, password string) (*UserResponse, error) {
csrfToken := resp.Header.Get("X-CSRF-Token")
// 2. GET 获取该用户的详细信息
usersURL := fmt.Sprintf("http://bs.seersun.com/api/users/%d", tokenResp.UserID)
usersURL := bbsurl + fmt.Sprintf("/api/users/%d", tokenResp.UserID)
req2, err := http.NewRequest("GET", usersURL, nil)
if err != nil {
return nil, fmt.Errorf("创建请求失败: %w", err)

View File

@@ -5,7 +5,6 @@ import (
"blazing/modules/config/model"
"blazing/modules/dict/service"
"strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
@@ -31,8 +30,6 @@ func NewPetFusionMaterialService() *PetFusionMaterialService {
// 获取融合材料的特性,返回两个值,一个是指定的特性,另一个是如果配方没找到的情况下,默认的配置
func (s *PetFusionMaterialService) Data(Material1 [4]uint32) uint32 {
cacheKey := strings.Join(gconv.Strings(Material1[:]), ":")
println(cacheKey, "获取融合id")
fusions := service.NewDictInfoService().GetData("fusion")
for _, v := range Material1 {

View File

@@ -71,9 +71,15 @@ func NewServerService() *ServerService {
cf.manager = storage.NewBucketManager(mac, &cfg)
return cf
}
func (s *ServerService) GetPort() gdb.List {
func (s *ServerService) GetPort(isdebug int) gdb.List {
var res gdb.Result
if isdebug == 1 {
res, _ = cool.DBM(s.Model).Where("is_open", 1).Fields("ip", "port", "online_id", "is_vip", "name").All()
res, _ := cool.DBM(s.Model).Where("is_open", 1).Fields("ip", "port", "online_id", "is_vip", "name").All()
} else {
res, _ = cool.DBM(s.Model).Where("is_open", 1).Where("is_debug", 0).Fields("ip", "port", "online_id", "is_vip", "name").All()
}
return res.List()
@@ -85,16 +91,17 @@ func (s *ServerService) GetServer() []model.ServerList {
return item
}
func (s *ServerService) StartUPdate(OnlineID uint16) model.ServerList {
func (s *ServerService) StartUPdate(OnlineID uint16, isinstall int) model.ServerList {
m := cool.DBM(s.Model).Where("online_id", OnlineID)
var tttt model.ServerList
m.Scan(&tttt)
if isinstall == 1 {
tttt.IsOpen = uint8(0)
m.Save(tttt)
}
tttt.IsOpen = 0
m.Save(tttt)
// s.CleanCache()
return tttt

View File

@@ -88,6 +88,8 @@ func (s *DictInfoService) GetData(types string) (data map[uint32]model.DictInfo)
return fusions
}
// 获取物品的最大数限制
func (s *DictInfoService) GetMax(value uint32) (max uint32) {
m := cool.DBM(s.Model)
@@ -105,6 +107,21 @@ func (s *DictInfoService) GetMax(value uint32) (max uint32) {
}
// 获取稀有精灵的光环显示
func (s *DictInfoService) GetShiny() []int {
//获取精灵的排序作为精灵的数组
m := cool.DBM(s.Model)
res, _ := m.Where("typeId", 10).Where("ordernum", 1).Cache(gdb.CacheOption{
// Duration: time.Hour,
Force: false,
}).Fields("value").All()
return res.Array("value").Ints()
}
// ModifyAfter 修改后
func (s *DictInfoService) ModifyAfter(ctx context.Context, method string, param map[string]interface{}) (err error) {
defer s.Service.ModifyAfter(ctx, method, param)

View File

@@ -24,13 +24,14 @@ var MilestoneEnum = enum.New[struct {
type EnumMilestone int
// var MilestoneMode = enum.New[struct {
// BOSS EnumMilestone //boss类 地图ID->BOSSID ,胜利次数 mapid bossid petid防止换boss后数据不可用
// ITEM EnumMilestone //物品类 物品ID 使用精灵
// Fight EnumMilestone //挑战类 对战模式->对战类型->1是赢,0是总局数
// Moster EnumMilestone //野怪统计 地图ID->怪物ID
// Task EnumMilestone
// }]()
var MilestoneMode = enum.New[struct {
BOSS EnumMilestone //boss类 地图ID->BOSSID ,胜利次数 mapid bossid petid防止换boss后数据不可用
ITEM EnumMilestone //物品类 物品ID 使用精灵
Fight EnumMilestone //挑战类 对战模式->对战类型->1是赢,0是总局数
Moster EnumMilestone //野怪统计 地图ID->怪物ID
Task EnumMilestone
Pet EnumMilestone //宠物 属性->属性值->ID
}]()
const TableNameMilestone = "player_milestone"
@@ -39,10 +40,9 @@ type Milestone struct {
Base
PlayerID uint64 `gorm:"not null;index:idx_milestone_by_player_id;comment:'所属玩家ID'" json:"player_id"`
DoneType EnumMilestone `gorm:"not null;comment:'里程碑类型'" json:"done_type"`
Args string `gorm:"type:text;not null;comment:'里程碑ID'" json:"args"`
Args []int32 `gorm:"type:jsonb;not null;comment:'里程碑ID'" json:"args"`
// 注:不单独设置"里程碑ID",通过 PlayerID + DoneType + IDs 组合唯一标识一个里程碑(更灵活)
Results string `gorm:"type:jsonb;not null;comment:'里程碑参数'" json:"results"`
Count uint32 `gorm:"not null;comment:'里程碑完成次数'" json:"count"`
Results []int32 `gorm:"type:jsonb;not null;comment:'里程碑参数'" json:"results"`
}
// // MilestoneEX 里程碑扩展结构体,用于业务层解析后的数据操作

View File

@@ -78,6 +78,17 @@ const (
Reserved TaskStatus = 2 // 预留AS3 中映射为未接受)
)
// 定义检查函数判断84-87索引中是否有任意一个元素不等于3
func (lw *PlayerInfo) IsNewPlayer() bool {
// 遍历84到87的索引
for i := 85; i <= 88; i++ {
if lw.GetTask(i) != Completed {
return true // 只要有一个不等于3就返回true
}
}
return false // 全部等于3则返回false
}
// SetTask 设置第 i 个任务的状态0 ≤ i < 2000
func (m *PlayerInfo) SetTask(i int, status TaskStatus) error {
i-- //下标减1

View File

@@ -80,6 +80,34 @@ func (s *InfoService) SetLogin() *model.PlayerInfo {
}
tt.Data.AllPetNumber = uint32(NewPetService(s.userid).PetCount(0))
if tt.Data.MapID > 300 || tt.Data.MapID == 0 { //如果位于基地,就重置到传送仓
tt.Data.MapID = 1
}
if tt.Data.IsNewPlayer() { //重置新手地图,放到机械仓
tt.Data.SetTask(4, model.Completed) //设置新手任务默认完成
tt.Data.MapID = 8
if len(tt.Data.PetList) == 0 {
//这个是添加后防止卡死
rr := NewPetService(s.userid).PetInfo(0)
if len(rr) > 0 {
tt.Data.PetList = append(tt.Data.PetList, rr[0].Data)
}
}
}
if tt.Data.MaxPuniLv < 9 {
for i := 291; i < 299; i++ {
if tt.Data.GetTask(i) == model.Completed {
tt.Data.MaxPuniLv = uint32(i) - 290
}
}
}
if !IsToday(tt.LastResetTime) { //判断是否是今天
//每天login时候检查重置时间然后把电池任务挖矿重置

BIN
public/logic-linux-amd64_1 Normal file

Binary file not shown.