pet_home_server/src/server/game/admin.go
2026-04-01 10:21:16 +08:00

443 lines
13 KiB
Go

package game
import (
"encoding/json"
"fmt"
"runtime"
"server/MergeConst"
"server/conf"
"server/db"
Msg "server/game/mod/msg"
GoUtil "server/game_util"
"server/gamedata"
"server/msg"
"time"
"gitea.bywaystudios.com/pet_home/leaf/gate"
"gitea.bywaystudios.com/pet_home/leaf/log"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/mem"
"google.golang.org/protobuf/proto"
)
var AdminFuncMap = map[string]func([]interface{}) error{
"ReqAdminInfo": AdminPlayerInfo,
"ReqServerInfo": ReqServerInfo,
"ReqReloadServerMail": ReqReloadServerMail,
"ReqReload": ReqReload,
"ReqAdminGm": ReqAdminGm,
"ReqAdminBan": ReqAdminBan,
"ReqAdminShipping": ReqAdminShipping,
}
func AdminProcess(funcName string, args []interface{}) {
defer func() {
if r := recover(); r != nil {
log.Error("uid : %d, func : %s, fatal : %s", 0, funcName, r)
//GoUtil.SendFeishuFatal(0, funcName, fmt.Sprintf("fatal : %s", r))
}
}()
if f, ok := AdminFuncMap[funcName]; ok {
err := f(args)
if err != nil {
log.Debug("AdminProcess error: %v", err)
}
return
}
log.Debug("AdminProcess error: %v", "Func not found")
}
func VerifyUser(accountInfo *db.Db_Account, detail *msg.ReqLogin) (ResLogin *msg.ResLogin, accountInfoOut *db.Db_Account) {
if detail.Type == msg.LOGIN_TYPE_CODE_LOGIN {
err := VerifyCode(detail.UserName, detail.Code)
if err != nil {
ResLogin = &msg.ResLogin{
ResultCode: MergeConst.Protocol_Error_Account_Code_Error,
DwUin: 0,
}
return
}
}
if detail.Type == msg.LOGIN_TYPE_SDK_LOGIN {
if accountInfo == nil {
accountInfo = db.GetAccountInfoFromDb(detail.Device)
}
if accountInfo != nil {
db.UpdateAccountInfoName(accountInfo, detail.UserName)
accountInfo.UserName = detail.UserName
db.UpdatePlayerBaseInfoName(detail.Device, detail.UserName)
}
}
if accountInfo == nil {
ResLogin = &msg.ResLogin{
ResultCode: MergeConst.Protocol_Error_Account_NoExsit,
DwUin: 0,
}
return
}
if detail.Type == msg.LOGIN_TYPE_ACCOUNT_LOGIN && accountInfo.UserPassword != detail.UserPwd {
ResLogin = &msg.ResLogin{
ResultCode: MergeConst.Protocol_Error_Account_OR_PWD_ERROR,
DwUin: 0,
}
return
}
if detail.Type == msg.LOGIN_TYPE_DEVICE_LOGIN {
if detail.Device != accountInfo.DeviceId {
ResLogin = &msg.ResLogin{
ResultCode: MergeConst.Protocol_Error_Account_Device_Error,
DwUin: 0,
}
return
}
}
playerbaseinfo := db.GetPlayerBaseInfoFromDbByName(detail.UserName)
if playerbaseinfo == nil {
ResLogin = &msg.ResLogin{
ResultCode: MergeConst.Protocol_Error_Account_NoExsit,
DwUin: 0,
}
return
}
if playerbaseinfo.Ban > GoUtil.Now() || playerbaseinfo.Ban == -1 {
ResLogin = &msg.ResLogin{
ResultCode: MergeConst.Protocol_Error_Account_Ban,
DwUin: 0,
}
return
}
accountInfoOut = accountInfo
ResLogin = &msg.ResLogin{
ResultCode: 0,
DwUin: playerbaseinfo.DwUin,
FaceBookId: playerbaseinfo.FaceBookId,
UserName: playerbaseinfo.UserName,
}
return
}
func ReqAdminShipping(args []interface{}) error {
a, buf := ParseAdminArgs(args)
req := &msg.ReqAdminShipping{}
proto.Unmarshal(buf, req)
res := make(map[string]interface{})
res["Code"] = 0
orderInfo, err := db.GetPlayerChargeData(req.OrderSn)
if err != nil {
res["Code"] = 1
res["Msg"] = "order not found"
AdminPlayerBack(a, res)
}
if orderInfo.PayStatus == MergeConst.ORDER_STATUS_SHIP {
res["Msg"] = "order already shipped"
AdminPlayerBack(a, res)
}
player := G_GameLogicPtr.GetPlayer(int64(orderInfo.Uid))
if player != nil {
go player.TriggerShippingOrderOrigin(&msg.ReqShippingOrder{
OrderSn: req.OrderSn,
})
res["Msg"] = "player online,triggered sync"
AdminPlayerBack(a, res)
} else {
orderInfo.PayStatus = MergeConst.ORDER_STATUS_PAY
orderInfo.PayChannelOrderId = req.ChannelOrderSn
db.UpdatePlayerChargeData(orderInfo)
}
return nil
}
func AdminPlayerInfo(args []interface{}) error {
a, buf := ParseAdminArgs(args)
req := &msg.ReqAdminInfo{}
proto.Unmarshal(buf, req)
player := G_GameLogicPtr.GetPlayer(req.Uid)
online := true
if player == nil {
player = new(Player)
player.M_DwUin = req.Uid
player.InitPlayerOnly()
player.ZeroUpdate(nil)
online = false
}
res := make(map[string]interface{})
res["Name"] = player.PlayMod.getBaseMod().NickName
res["Uid"] = player.M_DwUin
res["AreaId"] = player.PlayMod.getDecorateMod().GetAreaId()
res["Face"] = player.PlayMod.getFaceMod().SetId
res["Charge"] = player.PlayMod.getChargeMod().Charge
res["MaxCharge"] = player.PlayMod.getChargeMod().MaxCharge
res["Level"] = player.GetPlayerBaseMod().GetLevel()
res["Diamond"] = player.GetPlayerBaseMod().GetDiamond()
res["Star"] = player.GetPlayerBaseMod().GetStar()
res["Energy"] = player.GetPlayerBaseMod().GetEnergy()
res["Mac"] = player.GetPlayerBaseMod().GetName()
res["Login"] = player.PlayMod.getBaseMod().LoginTime
res["Cumulative"] = player.PlayMod.getBaseMod().Cumulative
res["RegisterTime"] = player.GetPlayerBaseMod().GetRegisterTime()
res["TodayCumulative"] = player.PlayMod.getBaseMod().TodayCumulative
res["Ban"] = db.GetPlayerBan(player.PlayMod.getBaseMod().Account)
if online {
res["Cumulative"] = int64(player.PlayMod.getBaseMod().Cumulative) + GoUtil.Now() - int64(player.PlayMod.getBaseMod().LoginTime)
res["TodayCumulative"] = int64(player.PlayMod.getBaseMod().TodayCumulative) + GoUtil.Now() - int64(player.PlayMod.getBaseMod().LoginTime)
}
res["Bonus"] = player.PlayMod.getLimitedTimeEventMod().Progress
res["Code"] = player.PlayMod.getBaseMod().AddCode
res["ChessMap"] = player.PlayMod.getChessMod().ChessMap
res["ActLog"] = player.PlayMod.getFriendMod().ActivityLog
res["AdWatch"] = player.PlayMod.getKvMod().GetAdValue()
friendList := player.PlayMod.getFriendMod().NewFriendList
type friendInfo struct {
Uid int64
NickName string
Avatar int
Level int
LogoutTime int64
LoginTime int64
}
resFriendList := make([]friendInfo, 0, len(friendList))
for v := range friendList {
ps := G_GameLogicPtr.GetSimplePlayerByUid(v)
if ps == nil {
continue
}
resFriendList = append(resFriendList, friendInfo{
Uid: int64(v),
NickName: ps.Name,
Avatar: ps.Face,
Level: ps.Level,
LogoutTime: ps.Loginout,
LoginTime: ps.Login,
})
}
res["FriendList"] = resFriendList
OrderMap := make(map[int]interface{})
Index := 0
for k, v := range player.PlayMod.getOrderMod().OrderList {
OrderMap[Index] = map[string]interface{}{
"Id": k,
"Type": v.Type,
"Time": v.Timestamp,
"ChessId": GoUtil.IntSliceToString(v.MergeId),
"Diff": v.Diff,
}
Index++
}
res["Order"] = OrderMap
AdminPlayerBack(a, res)
return nil
}
func AdminPlayerBack(a gate.Agent, res map[string]interface{}) {
jsonBuff, _ := json.Marshal(res)
response := &msg.AdminRes{}
response.Func = "admin"
response.Info = string(jsonBuff)
a.WriteMsg(response)
}
func ReqServerInfo(args []interface{}) error {
a, _ := ParseAdminArgs(args)
res := make(map[string]interface{})
res["PlayerNum"] = G_GameLogicPtr.GetPlayerNum()
res["StartTime"] = G_GameLogicPtr.GetStartTime()
var m runtime.MemStats
runtime.ReadMemStats(&m)
res["TotalAlloc"] = fmt.Sprintf("%dM", m.TotalAlloc/(1024*1024))
// 2. 获取系统内存使用信息
vmStat, _ := mem.VirtualMemory()
// 3. 获取 CPU 使用率(一秒内采样)
cpuPercent, err := cpu.Percent(time.Second, false)
if err == nil && len(cpuPercent) > 0 {
res["CPU"] = cpuPercent[0]
}
res["Alloc"] = fmt.Sprintf("%dM", m.Alloc/(1024*1024))
res["Sys"] = m.Sys / (1024 * 1024)
res["NumGC"] = m.NumGC
res["NumGoroutine"] = runtime.NumGoroutine()
if vmStat != nil {
res["FreeMem"] = vmStat.Available / (1024 * 1024)
res["UsageMem"] = vmStat.Used / (1024 * 1024)
} else {
res["UsageMem"] = 0
res["FreeMem"] = 0
}
res["Version"] = conf.Server.Version
AdminPlayerBack(a, res)
return nil
}
func ReqReloadServerMail(args []interface{}) error {
G_GameLogicPtr.MailMgrCall(&Msg.Msg{Type: Msg.HANDLE_TYPE_MAIL_RELOAD})
G_GameLogicPtr.NotifyAll(&Msg.Msg{Type: Msg.HANDLE_TYPE_MAIL})
log.Debug("ReqReloadServerMail success")
return nil
}
func ReqReload(args []interface{}) error {
a, _ := ParseAdminArgs(args)
gamedata.Reload()
res := make(map[string]interface{})
res["Code"] = 0
AdminPlayerBack(a, res)
return nil
}
func ReqAdminGm(args []interface{}) error {
a, buf := ParseAdminArgs(args)
req := &msg.ReqAdminGm{}
proto.Unmarshal(buf, req)
res := make(map[string]interface{})
res["Code"] = 0
res["Msg"] = "ok"
player := G_GameLogicPtr.GetPlayer(req.Uid)
if player == nil {
res["Code"] = 1
res["Msg"] = "player not found"
AdminPlayerBack(a, res)
return nil
}
player.lock.Lock()
defer player.lock.Unlock()
err := ReqGmCommand_(player, req.Command)
if err != nil {
res["Code"] = 1
res["Msg"] = err.Error()
AdminPlayerBack(a, res)
return err
}
AdminPlayerBack(a, res)
return nil
}
func ReqAdminBan(args []interface{}) error {
a, buf := ParseAdminArgs(args)
req := &msg.ReqAdminBan{}
proto.Unmarshal(buf, req)
res := make(map[string]interface{})
res["Code"] = 0
res["Msg"] = "ok"
db.UpdatePlayerBan(req.Uid, int64(req.Time))
AdminPlayerBack(a, res)
return nil
}
func AcitivityCfgReload() {
G_GameLogicPtr.ActivityMgr.Reload()
}
func AdminShipping(req *msg.ReqOrderShipping) (*msg.ResOrderShipping, error) {
res := &msg.ResOrderShipping{}
res.Code = 0
orderInfo, err := db.GetPlayerChargeData(req.OrderSn)
if err != nil {
res.Code = 1
res.Msg = "order not found"
}
if orderInfo.PayStatus == MergeConst.ORDER_STATUS_SHIP {
res.Msg = "order already shipped"
}
// 玩家在线,通知发货
player := G_GameLogicPtr.GetPlayer(int64(orderInfo.Uid))
if player != nil {
go player.TriggerShippingOrderOrigin(&msg.ReqShippingOrder{
OrderSn: req.OrderSn,
})
res.Msg = "player online,triggered sync"
}
return res, nil
}
func AdminPlayerDetailInfo(req *msg.UserDetailParam) (*msg.ResUserDetail, error) {
player := G_GameLogicPtr.GetPlayer(req.Uid)
online := true
if player == nil {
player = new(Player)
player.M_DwUin = req.Uid
player.InitPlayerOnly()
player.ZeroUpdate(nil)
online = false
}
banTime := db.GetPlayerBan(player.PlayMod.getBaseMod().Account)
actLog := make([]*msg.ActLog, 0, len(player.PlayMod.getFriendMod().ActivityLog))
for _, v := range player.PlayMod.getFriendMod().ActivityLog {
actLog = append(actLog, &msg.ActLog{
Type: int32(v.Type),
Time: v.Time,
Param: v.Param,
})
}
info := &msg.ResUserDetailInfo{
Name: player.PlayMod.getBaseMod().Account,
Uid: player.M_DwUin,
AreaId: int32(player.PlayMod.getDecorateMod().GetAreaId()),
Face: int32(player.PlayMod.getFaceMod().SetId),
Charge: int32(player.PlayMod.getChargeMod().Charge),
MaxCharge: int32(player.PlayMod.getChargeMod().MaxCharge),
Level: int32(player.GetBaseMod().GetLevel()),
Diamond: int64(player.GetBaseMod().GetDiamond()),
Star: int32(player.GetBaseMod().GetStar()),
Energy: int32(player.GetBaseMod().GetEnergy()),
Mac: player.GetBaseMod().DiviceId,
Login: int64(player.GetBaseMod().LoginTime),
Cumulative: int64(player.PlayMod.getBaseMod().Cumulative),
RegisterTime: player.GetPlayerBaseMod().GetRegisterTime(),
TodayCumulative: int64(player.PlayMod.getBaseMod().TodayCumulative),
Ban: banTime > GoUtil.Now() || banTime == -1,
Bonus: int32(player.PlayMod.getLimitedTimeEventMod().Progress),
Code: player.PlayMod.getBaseMod().AddCode,
ActLog: actLog,
AdWatch: int32(player.PlayMod.getKvMod().GetAdValue()),
ChessMap: player.PlayMod.getChessMod().ChessMap,
}
if online {
info.Cumulative = int64(player.PlayMod.getBaseMod().Cumulative) + GoUtil.Now() - int64(player.PlayMod.getBaseMod().LoginTime)
info.TodayCumulative = int64(player.PlayMod.getBaseMod().TodayCumulative) + GoUtil.Now() - int64(player.PlayMod.getBaseMod().LoginTime)
}
friendList := player.PlayMod.getFriendMod().NewFriendList
info.FriendList = make([]*msg.UserDetailFriendInfo, 0, len(friendList))
for uid := range friendList {
ps := G_GameLogicPtr.GetSimplePlayerByUid(uid)
if ps == nil {
continue
}
info.FriendList = append(info.FriendList, &msg.UserDetailFriendInfo{
Uid: int64(uid),
NickName: ps.Name,
Avatar: int32(ps.Face),
Level: int32(ps.Level),
LogoutTime: ps.Loginout,
LoginTime: ps.Login,
})
}
orderList := player.PlayMod.getOrderMod().OrderList
info.Order = make([]*msg.UserDetailOrderInfo, 0, len(orderList))
for orderID, order := range orderList {
chessArr := make([]*msg.UserDetailOrderInfoChess, 0, len(order.MergeId))
for _, chessID := range order.MergeId {
chessArr = append(chessArr, &msg.UserDetailOrderInfoChess{
Id: int32(chessID),
})
}
info.Order = append(info.Order, &msg.UserDetailOrderInfo{
Id: fmt.Sprint(orderID),
Type: int32(order.Type),
Time: order.Timestamp,
Chess: chessArr,
Diff: int32(order.Diff),
})
}
return &msg.ResUserDetail{
Code: 0,
Msg: "ok",
Info: info,
}, nil
}