```
feat(common): 添加GlowFilter的Level字段 添加了GlowFilter结构体中的Level字段,用于表示等级信息, 对应JSON标签为"level,omitempty" --- fix(utils): 修复concurrent_swiss_map中的panic处理 - 使用goroutine替代线程池来监听通道 - 添加panic恢复机制,当发生panic时记录错误日志 - 确保在异常情况下程序能够
This commit is contained in:
@@ -47,6 +47,7 @@ type GlowFilter struct {
|
|||||||
// Knockout 是否挖空,默认 false
|
// Knockout 是否挖空,默认 false
|
||||||
Knockout bool `json:"knockout,omitempty"`
|
Knockout bool `json:"knockout,omitempty"`
|
||||||
ColorMatrixFilter [20]float32 `json:"matrix,omitempty"`
|
ColorMatrixFilter [20]float32 `json:"matrix,omitempty"`
|
||||||
|
Level uint8 `json:"level,omitempty"` //等级
|
||||||
}
|
}
|
||||||
|
|
||||||
// ItemInfo
|
// ItemInfo
|
||||||
|
|||||||
@@ -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 {
|
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
|
var wg sync.WaitGroup
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
m.pool.Submit(func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil { // 恢复 panic,err 为 panic 错误值
|
||||||
|
// 1. 打印错误信息
|
||||||
|
|
||||||
|
cool.Logger.Error(context.TODO(), "panic 错误:", err)
|
||||||
|
|
||||||
|
}
|
||||||
|
}()
|
||||||
for t := range ch {
|
for t := range ch {
|
||||||
if stop := f(t.Key, t.Val); stop {
|
if stop := f(t.Key, t.Val); stop {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}()
|
||||||
|
|
||||||
return &wg
|
return &wg
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.Info.UserID = data.Head.UserID
|
||||||
currentPlayer.Logintime = uint32(time.Now().Unix()) //保存时间戳
|
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)
|
defer space.GetSpace(currentPlayer.Info.MapID).EnterMap(currentPlayer)
|
||||||
|
|
||||||
return result, 0
|
return result, 0
|
||||||
|
|||||||
@@ -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))
|
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 {
|
for _, v := range data.Item1 {
|
||||||
if c.Service.Item.CheakItem(v) == 0 {
|
if c.Service.Item.CheakItem(v) == 0 {
|
||||||
return &pet.PetFusionInfo{}, 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
|
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)))
|
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)))
|
dv2 := alpacadecimal.NewFromInt(1).Div(alpacadecimal.NewFromInt(3)).Mul(alpacadecimal.NewFromInt(int64(Auxpetinfo.Dv)))
|
||||||
dv := dv1.Add(dv2).Add(alpacadecimal.NewFromInt(1)).IntPart()
|
dv := dv1.Add(dv2).Add(alpacadecimal.NewFromInt(1)).IntPart()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
// 免疫瞬杀
|
// 免疫瞬杀
|
||||||
type NewSel114 struct {
|
type NewSel114 struct {
|
||||||
NewSel0
|
NewSel0
|
||||||
v *input.Effect
|
v []*input.Effect
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *NewSel114) TurnStart(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) {
|
func (e *NewSel114) TurnStart(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) {
|
||||||
@@ -17,21 +17,23 @@ func (e *NewSel114) TurnStart(fattack *action.SelectSkillAction, sattack *action
|
|||||||
return
|
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 {
|
if v.ID().GetEffectType() == input.EffectType.NewSel && v.ID().Suffix() == 32 {
|
||||||
v.Alive()
|
v.Alive(false)
|
||||||
e.v = &v
|
e.v = append(e.v, &v)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
func (e *NewSel114) TurnEnd() {
|
func (e *NewSel114) TurnEnd() {
|
||||||
if e.v != nil {
|
for _, v := range e.v {
|
||||||
|
if v != nil {
|
||||||
e.Alive(true)
|
e.Alive(true)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func (p *Player) GenMonster() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
if cool.Config.ServerInfo.IsVip != 0 { //测试服,百分百异色
|
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) {
|
if xmlres.PetMAP[int(p.OgreInfo.Data[i].Id)].CatchRate != 0 && grand.Meet(3, 1000) {
|
||||||
p.OgreInfo.Data[i].RandSHiny()
|
p.OgreInfo.Data[i].RandSHiny()
|
||||||
|
|||||||
@@ -46,6 +46,18 @@ type OgrePetInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *OgrePetInfo) RandSHiny() {
|
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
|
var co *data.GlowFilter
|
||||||
if o.Ext == 0 {
|
if o.Ext == 0 {
|
||||||
|
|
||||||
@@ -222,7 +234,7 @@ func (p *Player) ItemAdd(ItemId, ItemCnt uint32) (result bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (player1 *Player) Kick(qtype int) {
|
func (player1 *Player) Kick(qtype int) {
|
||||||
if player1.IsLogin {
|
|
||||||
//取成功,否则创建
|
//取成功,否则创建
|
||||||
//player1.Save() //先保存数据再返回
|
//player1.Save() //先保存数据再返回
|
||||||
head := common.NewTomeeHeader(1001, player1.Info.UserID)
|
head := common.NewTomeeHeader(1001, player1.Info.UserID)
|
||||||
@@ -242,7 +254,7 @@ func (player1 *Player) Kick(qtype int) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
<-CloseChan
|
<-CloseChan
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Cheak(b error) {
|
func (p *Player) Cheak(b error) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package player
|
|||||||
import (
|
import (
|
||||||
"blazing/common/data/share"
|
"blazing/common/data/share"
|
||||||
"blazing/cool"
|
"blazing/cool"
|
||||||
"blazing/modules/player/model"
|
"fmt"
|
||||||
|
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
"blazing/logic/service/space"
|
"blazing/logic/service/space"
|
||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
// Save 保存玩家数据
|
// Save 保存玩家数据
|
||||||
func (p *Player) Save() {
|
func (p *Player) Save() {
|
||||||
|
cool.CacheManager.Remove(context.TODO(), fmt.Sprintf("player:%d", p.Info.UserID))
|
||||||
if cool.Config.ServerInfo.IsVip != 0 {
|
if cool.Config.ServerInfo.IsVip != 0 {
|
||||||
cool.Logger.Info(context.TODO(), "测试服不保存玩家数据", p.Info.UserID)
|
cool.Logger.Info(context.TODO(), "测试服不保存玩家数据", p.Info.UserID)
|
||||||
|
|
||||||
@@ -57,10 +58,9 @@ func (p *Player) Save() {
|
|||||||
|
|
||||||
p.MapNPC.Stop() //停止刷怪
|
p.MapNPC.Stop() //停止刷怪
|
||||||
|
|
||||||
p.IsLogin = false
|
|
||||||
|
|
||||||
Mainplayer.Delete(p.Info.UserID)
|
Mainplayer.Delete(p.Info.UserID)
|
||||||
share.ShareManager.DeleteUserOnline(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
|
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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -41,10 +41,10 @@ type LoginMSInfo struct {
|
|||||||
model.PlayerInfo
|
model.PlayerInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOutInfo() *LoginMSInfo {
|
func NewOutInfo(info *model.PlayerInfo) *LoginMSInfo {
|
||||||
|
|
||||||
l := &LoginMSInfo{
|
l := &LoginMSInfo{
|
||||||
PlayerInfo: model.NewPlayerInfo(),
|
PlayerInfo: *info,
|
||||||
}
|
}
|
||||||
|
|
||||||
return l
|
return l
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"blazing/modules/base/service"
|
"blazing/modules/base/service"
|
||||||
|
|
||||||
config "blazing/modules/config/service"
|
config "blazing/modules/config/service"
|
||||||
|
dict "blazing/modules/dict/service"
|
||||||
blazing "blazing/modules/player/service"
|
blazing "blazing/modules/player/service"
|
||||||
playerservice "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
|
res.IsReg = 1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
res.PetID = dict.NewDictInfoService().GetShiny()
|
||||||
if cool.Config.ServerInfo.IsDebug != 0 {
|
res.Server = config.NewServerService().GetPort(int(t1.Debug))
|
||||||
res.LoginAddr = "192.168.1.44" + ":" + cool.Config.LoginPort
|
|
||||||
} else {
|
|
||||||
res.LoginAddr = cool.Config.File.Domain + ":" + cool.Config.LoginPort
|
|
||||||
}
|
|
||||||
res.Server = config.NewServerService().GetPort()
|
|
||||||
// share.ShareManager.DeleteSession(t1)
|
// share.ShareManager.DeleteSession(t1)
|
||||||
ser := playerservice.NewUserService(uint32(t1.ID))
|
ser := playerservice.NewUserService(uint32(t1.ID))
|
||||||
kickErr := ser.Info.Kick(uint32(t1.ID))
|
kickErr := ser.Info.Kick(uint32(t1.ID))
|
||||||
@@ -94,8 +90,9 @@ type SessionRes struct {
|
|||||||
IsReg int `json:"isreg"`
|
IsReg int `json:"isreg"`
|
||||||
UserID int `json:"userid"`
|
UserID int `json:"userid"`
|
||||||
Session string `json:"session"`
|
Session string `json:"session"`
|
||||||
LoginAddr string `json:"loginaddr"`
|
|
||||||
Server gdb.List `json:"server"`
|
Server gdb.List `json:"server"`
|
||||||
|
PetID []int `json:"petid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegReq struct {
|
type RegReq struct {
|
||||||
|
|||||||
@@ -58,11 +58,8 @@ func init() {
|
|||||||
g.Server().BindHandler("/server/*", func(r *ghttp.Request) {
|
g.Server().BindHandler("/server/*", func(r *ghttp.Request) {
|
||||||
servert := new(ServerHandler)
|
servert := new(ServerHandler)
|
||||||
id := gconv.Uint16(r.URL.Query().Get("id"))
|
id := gconv.Uint16(r.URL.Query().Get("id"))
|
||||||
|
|
||||||
servert.isinstall = gconv.Uint32(r.URL.Query().Get("isinstall"))
|
servert.isinstall = gconv.Uint32(r.URL.Query().Get("isinstall"))
|
||||||
if servert.isinstall != 0 {
|
servert.ServerList = service.NewServerService().StartUPdate(id, int(servert.isinstall))
|
||||||
servert.ServerList = service.NewServerService().StartUPdate(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
upgrader := gws.NewUpgrader(servert, &gws.ServerOption{
|
upgrader := gws.NewUpgrader(servert, &gws.ServerOption{
|
||||||
|
|
||||||
|
|||||||
@@ -197,93 +197,11 @@ else
|
|||||||
command -v screen || { echo "❌ Screen安装失败"; exit 1; }
|
command -v screen || { echo "❌ Screen安装失败"; exit 1; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# 核心:无任何可能阻塞的命令,全程实时输出,100%不卡住 + 彻底清理所有logic会话
|
# 核心:无任何可能阻塞的命令,全程实时输出,100%不卡住 + 彻底清理所有logic会话
|
||||||
set -euo pipefail
|
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会话ID(1秒超时,避免漏查)
|
|
||||||
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}"
|
echo "目标路径:%s{exe_path}"
|
||||||
|
|
||||||
# 删除旧文件(关键修复:这里要判断目标路径,不是下载链接)
|
# 删除旧文件(关键修复:这里要判断目标路径,不是下载链接)
|
||||||
if [ -f "%s{exe_path}" ]; then
|
|
||||||
echo "删除旧文件:%s{exe_path}"
|
echo "删除旧文件:%s{exe_path}"
|
||||||
rm -f "%s{exe_path}"
|
rm -f "%s{exe_path}"
|
||||||
fi
|
|
||||||
|
|
||||||
echo "开始下载..."
|
echo "开始下载..."
|
||||||
DOWNLOAD_SUCCESS=0
|
DOWNLOAD_SUCCESS=0
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ type GroupAttributes struct {
|
|||||||
IsHidden int `json:"isHidden"`
|
IsHidden int `json:"isHidden"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bbsurl = "http://43.248.3.21:45632"
|
||||||
|
|
||||||
// GetUserInfo 输入用户名和密码,返回用户信息结构体
|
// GetUserInfo 输入用户名和密码,返回用户信息结构体
|
||||||
func GetUserInfo(username, password string) (*UserResponse, error) {
|
func GetUserInfo(username, password string) (*UserResponse, error) {
|
||||||
// 创建带 Cookie 存储的 HTTP 客户端
|
// 创建带 Cookie 存储的 HTTP 客户端
|
||||||
@@ -108,7 +110,7 @@ func GetUserInfo(username, password string) (*UserResponse, error) {
|
|||||||
client := &http.Client{Jar: jar}
|
client := &http.Client{Jar: jar}
|
||||||
|
|
||||||
// 1. POST 获取 token
|
// 1. POST 获取 token
|
||||||
tokenURL := "http://bs.seersun.com/api/token"
|
tokenURL := bbsurl + "/api/token"
|
||||||
formData := url.Values{}
|
formData := url.Values{}
|
||||||
formData.Set("identification", username)
|
formData.Set("identification", username)
|
||||||
formData.Set("password", password)
|
formData.Set("password", password)
|
||||||
@@ -141,7 +143,7 @@ func GetUserInfo(username, password string) (*UserResponse, error) {
|
|||||||
csrfToken := resp.Header.Get("X-CSRF-Token")
|
csrfToken := resp.Header.Get("X-CSRF-Token")
|
||||||
|
|
||||||
// 2. GET 获取该用户的详细信息
|
// 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)
|
req2, err := http.NewRequest("GET", usersURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("创建请求失败: %w", err)
|
return nil, fmt.Errorf("创建请求失败: %w", err)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"blazing/modules/config/model"
|
"blazing/modules/config/model"
|
||||||
"blazing/modules/dict/service"
|
"blazing/modules/dict/service"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
@@ -31,8 +30,6 @@ func NewPetFusionMaterialService() *PetFusionMaterialService {
|
|||||||
// 获取融合材料的特性,返回两个值,一个是指定的特性,另一个是如果配方没找到的情况下,默认的配置
|
// 获取融合材料的特性,返回两个值,一个是指定的特性,另一个是如果配方没找到的情况下,默认的配置
|
||||||
func (s *PetFusionMaterialService) Data(Material1 [4]uint32) uint32 {
|
func (s *PetFusionMaterialService) Data(Material1 [4]uint32) uint32 {
|
||||||
|
|
||||||
cacheKey := strings.Join(gconv.Strings(Material1[:]), ":")
|
|
||||||
println(cacheKey, "获取融合id")
|
|
||||||
fusions := service.NewDictInfoService().GetData("fusion")
|
fusions := service.NewDictInfoService().GetData("fusion")
|
||||||
|
|
||||||
for _, v := range Material1 {
|
for _, v := range Material1 {
|
||||||
|
|||||||
@@ -71,9 +71,15 @@ func NewServerService() *ServerService {
|
|||||||
cf.manager = storage.NewBucketManager(mac, &cfg)
|
cf.manager = storage.NewBucketManager(mac, &cfg)
|
||||||
return cf
|
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()
|
return res.List()
|
||||||
|
|
||||||
@@ -85,16 +91,17 @@ func (s *ServerService) GetServer() []model.ServerList {
|
|||||||
return item
|
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)
|
m := cool.DBM(s.Model).Where("online_id", OnlineID)
|
||||||
|
|
||||||
var tttt model.ServerList
|
var tttt model.ServerList
|
||||||
m.Scan(&tttt)
|
m.Scan(&tttt)
|
||||||
|
if isinstall == 1 {
|
||||||
tttt.IsOpen = 0
|
tttt.IsOpen = uint8(0)
|
||||||
|
|
||||||
m.Save(tttt)
|
m.Save(tttt)
|
||||||
|
}
|
||||||
|
|
||||||
// s.CleanCache()
|
// s.CleanCache()
|
||||||
return tttt
|
return tttt
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ func (s *DictInfoService) GetData(types string) (data map[uint32]model.DictInfo)
|
|||||||
return fusions
|
return fusions
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取物品的最大数限制
|
||||||
func (s *DictInfoService) GetMax(value uint32) (max uint32) {
|
func (s *DictInfoService) GetMax(value uint32) (max uint32) {
|
||||||
|
|
||||||
m := cool.DBM(s.Model)
|
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 修改后
|
// ModifyAfter 修改后
|
||||||
func (s *DictInfoService) ModifyAfter(ctx context.Context, method string, param map[string]interface{}) (err error) {
|
func (s *DictInfoService) ModifyAfter(ctx context.Context, method string, param map[string]interface{}) (err error) {
|
||||||
defer s.Service.ModifyAfter(ctx, method, param)
|
defer s.Service.ModifyAfter(ctx, method, param)
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ var MilestoneEnum = enum.New[struct {
|
|||||||
|
|
||||||
type EnumMilestone int
|
type EnumMilestone int
|
||||||
|
|
||||||
// var MilestoneMode = enum.New[struct {
|
var MilestoneMode = enum.New[struct {
|
||||||
// BOSS EnumMilestone //boss类 地图ID->BOSSID ,胜利次数 mapid bossid petid,防止换boss后数据不可用
|
BOSS EnumMilestone //boss类 地图ID->BOSSID ,胜利次数 mapid bossid petid,防止换boss后数据不可用
|
||||||
// ITEM EnumMilestone //物品类 物品ID 使用精灵
|
ITEM EnumMilestone //物品类 物品ID 使用精灵
|
||||||
// Fight EnumMilestone //挑战类 对战模式->对战类型->1是赢,0是总局数
|
Fight EnumMilestone //挑战类 对战模式->对战类型->1是赢,0是总局数
|
||||||
// Moster EnumMilestone //野怪统计 地图ID->怪物ID
|
Moster EnumMilestone //野怪统计 地图ID->怪物ID
|
||||||
// Task EnumMilestone
|
Task EnumMilestone
|
||||||
// }]()
|
Pet EnumMilestone //宠物 属性->属性值->ID
|
||||||
|
}]()
|
||||||
|
|
||||||
const TableNameMilestone = "player_milestone"
|
const TableNameMilestone = "player_milestone"
|
||||||
|
|
||||||
@@ -39,10 +40,9 @@ type Milestone struct {
|
|||||||
Base
|
Base
|
||||||
PlayerID uint64 `gorm:"not null;index:idx_milestone_by_player_id;comment:'所属玩家ID'" json:"player_id"`
|
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"`
|
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 组合唯一标识一个里程碑(更灵活)
|
// 注:不单独设置"里程碑ID",通过 PlayerID + DoneType + IDs 组合唯一标识一个里程碑(更灵活)
|
||||||
Results string `gorm:"type:jsonb;not null;comment:'里程碑参数'" json:"results"`
|
Results []int32 `gorm:"type:jsonb;not null;comment:'里程碑参数'" json:"results"`
|
||||||
Count uint32 `gorm:"not null;comment:'里程碑完成次数'" json:"count"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// // MilestoneEX 里程碑扩展结构体,用于业务层解析后的数据操作
|
// // MilestoneEX 里程碑扩展结构体,用于业务层解析后的数据操作
|
||||||
|
|||||||
@@ -78,6 +78,17 @@ const (
|
|||||||
Reserved TaskStatus = 2 // 预留(AS3 中映射为未接受)
|
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)
|
// SetTask 设置第 i 个任务的状态(0 ≤ i < 2000)
|
||||||
func (m *PlayerInfo) SetTask(i int, status TaskStatus) error {
|
func (m *PlayerInfo) SetTask(i int, status TaskStatus) error {
|
||||||
i-- //下标减1
|
i-- //下标减1
|
||||||
|
|||||||
@@ -80,6 +80,34 @@ func (s *InfoService) SetLogin() *model.PlayerInfo {
|
|||||||
}
|
}
|
||||||
tt.Data.AllPetNumber = uint32(NewPetService(s.userid).PetCount(0))
|
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) { //判断是否是今天
|
if !IsToday(tt.LastResetTime) { //判断是否是今天
|
||||||
|
|
||||||
//每天login时候检查重置时间,然后把电池,任务,挖矿重置
|
//每天login时候检查重置时间,然后把电池,任务,挖矿重置
|
||||||
|
|||||||
BIN
public/logic-linux-amd64_1
Normal file
BIN
public/logic-linux-amd64_1
Normal file
Binary file not shown.
Reference in New Issue
Block a user