From 4cdd576855c6e22d986ece4b18f7c80d82cefe38 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 03 六月 2025 14:21:15 +0800
Subject: [PATCH] 16 卡牌服务端(GMT命令:GMT_AddPayCoin、GMT_CTG)

---
 /dev/null                                                                                                                   |  124 ---------------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                          |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOfflineSupport.py                          |  115 ++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                                      |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_CTG.py        |   67 ++-----
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py                                            |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py      |   55 ++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py                    |   38 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py                            |   10 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_AddPayCoin.py |   49 ++++++
 10 files changed, 288 insertions(+), 179 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
index 26b114e..a9dcf21 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
@@ -2387,8 +2387,8 @@
 def SendGameErrorEx(errType, msgInfo="", playerID=0):
     ErrLog("SendGameErrorEx: %s -> %s" % (errType, msgInfo), playerID)
     SendGameError(errType, msgInfo)
-    #if GetGameWorld().GetDebugLevel():
-    #    raise Exception("%s -> %s" % (errType, msgInfo))
+    if GetGameWorld().GetDebugLevel():
+        raise Exception("%s -> %s" % (errType, msgInfo))
     return
 
 def SendGameError(errType, msgInfo=""):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index 07fb987..897af83 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -172,6 +172,7 @@
 import IPY_ServerDefine
 import CommFunc
 from PyMongoDB import RecvPackToMapDB
+import PyMongoMain
 import PlayerTalk
 
 import datetime
@@ -872,6 +873,7 @@
         pass
     
     else:
+        PyMongoMain.GetUserCtrlDB().OnPlayerLogin(curPlayer)
         PlayerMail.OnPlayerLogin(curPlayer)
         PlayerChatBox.OnPlayerLogin(curPlayer)
         PlayerFace.OnPlayerLogin(curPlayer)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
index 86b8bf3..4068544 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -96,6 +96,7 @@
 import PlayerFlashGiftbag
 import PlayerDailyGiftbag
 import PlayerFairyCeremony
+import PlayerOfflineSupport
 import PlayerNewFairyCeremony
 import PlayerActHorsePetFeast
 import PlayerFeastRedPacket
@@ -137,19 +138,14 @@
 
 def DoLogic_OnDay(tick):
     GameWorld.Log("MapServer -> OnDay!")
-    playerManager = GameWorld.GetPlayerManager()
-    #处理所有玩家信件的onday事件, 把存在时间+1
-    playerManager.ProcessAllPlayerMailOnDay()
-    
     #副本OnDay事件响应
     FBLogic.OnDay(tick)
     
-    #删除所有的任务发布
-    missionPubManager = GameWorld.GetGameWorld().GetDBMissionPubManager()
-    missionPubManager.Clear()
     #仙盟
     PlayerFamily.FamilyOnDay()
     
+    PlayerOfflineSupport.OnDay()
+    playerManager = GameWorld.GetPlayerManager()
     for i in xrange(playerManager.GetPlayerCount()):
         curPlayer = playerManager.GetPlayerByIndex(i)
         
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOfflineSupport.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOfflineSupport.py
new file mode 100644
index 0000000..3d4b3cb
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOfflineSupport.py
@@ -0,0 +1,115 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerOfflineSupport
+#
+# @todo:玩家离线支持能力
+# @author hxp
+# @date 2025-06-03
+# @version 1.0
+#
+# 详细描述: 主要用于处理离线玩家相关支持的能力
+# 典型应用:
+#     1. 后台GM工具命令,玩家不在线支持,规避后台操作一定要玩家在线的限制;
+#     2. 跨服通知的玩家相关操作信息
+#            由于子服跨服通讯有一定的延迟,所以确保某些通过跨服修改玩家相关信息命令在子服玩家离线时能在上线后执行
+#            如扣物品、货币或者给奖励等,防止由玩家离线后才收到消息引起的少扣或少给
+#     3. 其他
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-06-03 14:00"""
+#-------------------------------------------------------------------------------
+
+import DBDataMgr
+import GameWorld
+import ShareDefine
+import traceback
+import time
+
+def AddOfflineUnprocessed(playerID, eventName, eventData, outtimeDays=7):
+    '''添加玩家离线未处理的事件
+    @param eventName: 事件名
+    @param eventData: 事件数据,由功能自定定义,任意格式
+    @param outtimeDays: 过期天数,0-永久, >0-指定天数, 默认30天
+    '''
+    gameRecMgr = DBDataMgr.GetGameRecMgr()
+    recIDMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_PlayerOfflineUnprocessed, playerID)
+    recData = recIDMgr.AddRecData()
+    recData.SetValue1(outtimeDays)
+    recData.GetUserDict().update({"eventName":eventName, "eventData":eventData})
+    GameWorld.Log("添加玩家离线未处理的事件: %s, %s, %s" % (eventName, outtimeDays, eventData), playerID)
+    return
+
+def DoOfflineUnprocessed(curPlayer, eventName, dofunc):
+    '''执行处理玩家离线未处理的事件
+    @param dofunc: 执行函数,参数[curPlayer, recData, eventName, eventData]
+    '''
+    if not dofunc:
+        return
+    playerID = curPlayer.GetPlayerID()
+    recIDMgr = DBDataMgr.GetGameRecMgr().GetRecTypeIDMgr(ShareDefine.Def_GameRecType_PlayerOfflineUnprocessed, playerID)
+    # 必须按添加顺序执行,不然可能导致异常,如,先加1000金币,再扣除500,如果不按顺序执行可能导致最后金币与预期不符合
+    
+    delRecDataList = []
+    try:
+        for index in range(recIDMgr.GetCount()):
+            recData = recIDMgr.At(index)
+            recDict = recData.GetUserDict()
+            if recDict.get("eventName") != eventName:
+                continue
+            eventData = recDict.get("eventData")
+            GameWorld.Log("执行玩家上次离线前未处理事件: %s, %s" % (eventName, eventData), playerID)
+            dofunc(curPlayer, recData, eventName, eventData)
+            delRecDataList.append(recData)
+    except:
+        accID = curPlayer.GetAccID()
+        msgInfo = "eventName=%s,accID=%s, %s" % (eventName, accID, traceback.format_exc())
+        GameWorld.SendGameErrorEx("DoOfflineUnprocessed", msgInfo, playerID)
+        
+    # 执行完后再统一删除
+    for recData in delRecDataList:
+        recIDMgr.DelRecData(recData)
+        
+    return
+
+def DelOfflineUnprocessed(eventName):
+    ## 删除所有玩家某种离线未处理的事件
+    # @param eventName: 事件名
+    
+    delCnt = 0
+    recTypeMgr = DBDataMgr.GetGameRecMgr().GetRecTypeMgr(ShareDefine.Def_GameRecType_PlayerOfflineUnprocessed)
+    for recID in recTypeMgr.GetRecIDList():
+        recIDMgr = recTypeMgr.GetRecIDMgr(recID)
+        for index in range(recIDMgr.GetCount())[::-1]:
+            recData = recIDMgr.At(index)
+            if recData.GetUserDict().get("eventName") != eventName:
+                continue
+            recIDMgr.DelRecData(recData)
+            delCnt += 1
+            
+    GameWorld.DebugLog("删除玩家离线未处理的事件: %s, delCnt=%s" % (eventName, delCnt))
+    return
+
+def DelOuttimeOfflineUnprocessed():
+    ## 删除过期玩家离线未处理的事件
+    curTime = int(time.time())
+    recTypeMgr = DBDataMgr.GetGameRecMgr().GetRecTypeMgr(ShareDefine.Def_GameRecType_PlayerOfflineUnprocessed)
+    for recID in recTypeMgr.GetRecIDList():
+        recIDMgr = recTypeMgr.GetRecIDMgr(recID)
+        for index in range(recIDMgr.GetCount())[::-1]:
+            recData = recIDMgr.At(index)
+            recTime = recData.GetTime()
+            outtimeDays = recData.GetValue1()
+            if not outtimeDays:
+                continue
+            diffDays = GameWorld.GetDiff_Day(curTime, recTime) + 1
+            if diffDays <= outtimeDays:
+                continue
+            recIDMgr.DelRecData(recData)
+            GameWorld.DebugLog("删除玩家离线未处理的过期事件: %s, %s" % (outtimeDays, recData.GetUserData()), recID)
+    return
+
+def OnDay():
+    DelOuttimeOfflineUnprocessed()
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTAddPayCoin.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTAddPayCoin.py
deleted file mode 100644
index f2a14a8..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTAddPayCoin.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#-------------------------------------------------------------------------------
-#
-##@package Player.RemoteQuery.GY_Query_GMTAddPayCoin
-#
-# @todo:发放代币
-# @author hxp
-# @date 2024-01-02
-# @version 1.0
-#
-# 详细描述: 发放代币
-#
-#-------------------------------------------------------------------------------
-#"""Version = 2024-01-02 14:00"""
-#-------------------------------------------------------------------------------
-
-import GameWorld
-import DataRecordPack
-import PlayerControl
-import ShareDefine
-import GMCommon
-
-#逻辑实现 
-## 请求逻辑  
-#  @param query_Type 请求类型
-#  @param query_ID 玩家ID
-#  @param packCMDList 发包命令 
-#  @param tick 当前时间
-#  @return "True" or "False" or ""
-#  @remarks 函数详细说明.
-def DoLogic(query_Type, query_ID, packCMDList, tick):
-    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(query_ID)
-    
-    if not curPlayer or curPlayer.IsEmpty():
-        return
-    
-    Result = GMCommon.Def_Success
-    orderId, value, isOnlineGMT = packCMDList
-    
-    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_PayCoin, value, "GMTAdd")
-    
-    resultDict = {"value":value, "isOnlineGMT":isOnlineGMT, "nowPayCoin":PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_PayCoin)}
-    GameWorld.Log("GMTAddPayCoin: value=%s,isOnlineGMT=%s,resultDict=%s" % (value, isOnlineGMT, resultDict), curPlayer.GetPlayerID())
-    #流向 记录
-    DataRecordPack.DR_ToolGMOperate(query_ID, curPlayer.GetPlayerName(), curPlayer.GetAccID(), 'GMT_AddPayCoin', resultDict)
-    
-    if isOnlineGMT:
-        resultMsg = str([orderId, resultDict, 'GMT_AddPayCoin', Result])
-        GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GMToolResult', resultMsg, len(resultMsg))
-    return
-
-#执行结果
-## 执行结果
-#  @param curPlayer 发出请求的玩家
-#  @param callFunName 功能名称
-#  @param funResult 查询的结果
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
-def DoResult(curPlayer, callFunName, funResult, tick):
-    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTCTG.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTCTG.py
deleted file mode 100644
index 33a79ef..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_GMTCTG.py
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#---------------------------------------------------------------------
-#
-#---------------------------------------------------------------------
-##@package GY_Query_GMTCTG
-# @todo: CTG
-#
-# @author: whx
-# @date 2012-08-27 13:59
-# @version 1.2
-#
-# @note: 
-#
-# @change: "2014-05-19 14:40" Alee 资源补贴记录增加金额
-# @change: "2016-07-20 14:30" hxp 增加流向类型记录
-#---------------------------------------------------------------------
-#"""Version = 2016-07-20 14:30"""
-#---------------------------------------------------------------------
-#导入
-import GameWorld
-import DataRecordPack
-import PlayerCoin
-import ChConfig
-import GMCommon
-import ShareDefine
-import PlayerControl
-import IpyGameDataPY
-import IPY_GameWorld
-#---------------------------------------------------------------------
-#全局变量
-#---------------------------------------------------------------------
-#---------------------------------------------------------------------
-#逻辑实现 
-## 请求逻辑  
-#  @param query_Type 请求类型
-#  @param query_ID 玩家ID
-#  @param packCMDList 发包命令 
-#  @param tick 当前时间
-#  @return "True" or "False" or ""
-#  @remarks 函数详细说明.
-def DoLogic(query_Type, query_ID, packCMDList, tick):
-    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(query_ID)
-    
-    if not curPlayer or curPlayer.IsEmpty():
-        return
-    
-    Result = GMCommon.Def_Unknow
-    orderId, value, appID, isAddBourseMoney, isResult = packCMDList
-    
-    goldBefore = PlayerControl.GetMoneyReal(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money)
-    changeCoinPointBefore = curPlayer.GetChangeCoinPointTotal()
-    bourseMoneyBefore = PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney)
-    
-    errorMsg = ""
-    orderInfoIpyData = None
-    if appID:
-        orderInfoIpyData = IpyGameDataPY.GetIpyGameDataNotLog("OrderInfo", value, appID)
-        if not orderInfoIpyData:
-            Result = GMCommon.Def_ParamErr
-            errorMsg = "Can not found the orderInfo(%s) and appID(%s)!" % (value, appID)
-            
-    if errorMsg:
-        GameWorld.Log("GMT_CTG, errorMsg=%s" % errorMsg, query_ID)
-        resultMsg = str([orderId, errorMsg, 'GMT_CTG', Result])
-        GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GMToolResult', resultMsg, len(resultMsg))
-        return
-    
-    orderRMB = GameWorld.ToNumDef(value, None)
-    if not orderInfoIpyData and orderRMB != None:
-        if PlayerCoin.PlayerCoinToGoldEx(curPlayer, orderRMB, ChConfig.Def_GiveMoney_GMTCTG, isAddBourseMoney):
-            Result = GMCommon.Def_Success     
-        else:
-            errorMsg = "order error! value(%s)" % (value) 
-    else:
-        orderInfo = value
-        if PlayerCoin.DoGMCTG(curPlayer, orderInfo, appID, isAddBourseMoney, ChConfig.Def_GiveMoney_GMTCTG):
-            Result = GMCommon.Def_Success
-        else:
-            errorMsg = "orderInfo error! appID(%s), value(%s)" % (appID, value)
-            
-    if Result != GMCommon.Def_Success:
-        GameWorld.Log("GMT_CTG, errorMsg=%s" % errorMsg, query_ID)
-        resultMsg = str([orderId, errorMsg, 'GMT_CTG', Result])
-        GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GMToolResult', resultMsg, len(resultMsg))
-        return
-    
-    goldAfter = PlayerControl.GetMoneyReal(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money)
-    changeCoinPointAfter = curPlayer.GetChangeCoinPointTotal()
-    bourseMoneyAfter = PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney)
-    
-    resultDict = {"value":value, "appID":appID, "isAddBourseMoney":isAddBourseMoney, "Result":Result, 
-                  "gold":[goldBefore, goldAfter], "changeCoinPoint":[changeCoinPointBefore, changeCoinPointAfter], 
-                  "bourseMoney":[bourseMoneyBefore, bourseMoneyAfter]}
-    
-    GameWorld.Log("GMT_CTG, resultDict=%s" % resultDict, query_ID)
-    #流向 增加金额记录
-    DataRecordPack.DR_ToolGMOperate(query_ID, curPlayer.GetPlayerName(), curPlayer.GetAccID(), 'GMT_CTG', resultDict)
-    
-    if isResult:
-        resultMsg = str([orderId, resultDict, 'GMT_CTG', Result])
-        GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GMToolResult', resultMsg, len(resultMsg))
-    return
-
-#---------------------------------------------------------------------
-#执行结果
-## 执行结果
-#  @param curPlayer 发出请求的玩家
-#  @param callFunName 功能名称
-#  @param funResult 查询的结果
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
-def DoResult(curPlayer, callFunName, funResult, tick):
-    return
-
-
-
-
-
-
-
-
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_AddPayCoin.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_AddPayCoin.py
new file mode 100644
index 0000000..49ee321
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_AddPayCoin.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package PyMongoDB.GMToolLogicProcess.Commands.GMT_AddPayCoin
+#
+# @todo:GM工具命令 - 发放代币
+# @author hxp
+# @date 2025-06-03
+# @version 1.0
+#
+# 详细描述: GM工具命令 - 发放代币
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-06-03 14:00"""
+#-------------------------------------------------------------------------------
+
+import GMCommon
+import ShareDefine
+import DataRecordPack
+import PlayerControl
+import GameWorld
+
+## 执行逻辑
+#  @param curPlayer 当前玩家
+#  @param gmCmdDict: 命令字典
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(gmCmdDict):
+    errorMsg = ""
+    from GMToolLogicProcess import  ProjSpecialProcess
+    Result, curPlayer = ProjSpecialProcess.GMCmdPlayerValidation(gmCmdDict)
+    if Result != GMCommon.Def_Success:
+        return Result, errorMsg
+    if not curPlayer:
+        return Result, "玩家不在线,上线后处理"
+    
+    # 玩家在线,可处理
+    playerID = curPlayer.GetPlayerID()
+    Result = GMCommon.Def_Unknow
+    GMT_Name = gmCmdDict.get(GMCommon.Def_GMKey_Type, '') 
+    
+    value = GameWorld.ToIntDef(gmCmdDict.get('value', ''))
+    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_PayCoin, value, "GMTAdd")
+    
+    resultDict = {"value":value, "nowPayCoin":PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_PayCoin)}
+    #流向 记录
+    DataRecordPack.DR_ToolGMOperate(playerID, curPlayer.GetPlayerName(), curPlayer.GetAccID(), GMT_Name, resultDict)
+    return GMCommon.Def_Success, resultDict
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_CTG.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_CTG.py
index feab2a7..9929b80 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_CTG.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/Commands/GMT_CTG.py
@@ -1,66 +1,47 @@
 #!/usr/bin/python
 # -*- coding: GBK -*-
-#---------------------------------------------------------------------
+#-------------------------------------------------------------------------------
 #
-#---------------------------------------------------------------------
-##@package GMT_CTG
-# GM命令CTG
+##@package PyMongoDB.GMToolLogicProcess.Commands.GMT_CTG
 #
-# @author whx
-# @date 2012-08-27 13:59
+# @todo:GM工具命令 - CTG充值
+# @author hxp
+# @date 2025-06-03
 # @version 1.0
 #
-# @note
-#---------------------------------------------------------------------
-"""Version = 2012-08-27 13:59"""
-#---------------------------------------------------------------------
-#导入
+# 详细描述: GM工具命令 - CTG充值
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-06-03 14:00"""
+#-------------------------------------------------------------------------------
+
 import GMCommon
-from MangoDBCommon import fix_incomingText
 import GameWorld
 from Player import (PlayerControl, PlayerCoin)
 import IpyGameDataPY
 import IPY_GameWorld
-import ShareDefine
 import DataRecordPack
+import ShareDefine
 import ChConfig
-from PyMongoDB.GMToolLogicProcess import GMToolPyInterface
-import json
-#---------------------------------------------------------------------
-#全局变量
-
-#---------------------------------------------------------------------
 
 ## 收到gm命令执行
 # @param gmCmdDict:gm命令字典
 # @return None 
 def OnExec(gmCmdDict):
-    queryType = gmCmdDict.get(GMCommon.Def_GMKey_QueryType, '')
-    playerFind = gmCmdDict.get(GMCommon.Def_GMKey_PlayerFind, '')
-    Result = GMCommon.Def_ParamErr
+    
     errorMsg = ""
-    
-    if queryType not in [GMCommon.Def_GMKey_PlayerAccID, GMCommon.Def_GMKey_PlayerName]:
+    from GMToolLogicProcess import  ProjSpecialProcess
+    Result, curPlayer = ProjSpecialProcess.GMCmdPlayerValidation(gmCmdDict)
+    if Result != GMCommon.Def_Success:
         return Result, errorMsg
+    if not curPlayer:
+        return Result, "玩家不在线,上线后处理"
     
-    if len(playerFind) <= 0:
-        return Result, errorMsg
-    
-    curPlayer = None
-    if queryType == GMCommon.Def_GMKey_PlayerName:
-        curPlayer = GameWorld.GetPlayerManager().FindPlayerByName(playerFind)
-    else:
-        curPlayer = GameWorld.GetPlayerManager().FindPlayerByAccID(playerFind)
-    
-    if not curPlayer or curPlayer.IsEmpty():
-        Result = GMCommon.Def_Success
-        # 不在线
-        return Result, errorMsg
-
+    # 玩家在线,可处理
     playerID = curPlayer.GetPlayerID()
-    
     Result = GMCommon.Def_Unknow
-
+    GMT_Name = gmCmdDict.get(GMCommon.Def_GMKey_Type, '') 
+    
     value = gmCmdDict.get('value', '')
     appID = gmCmdDict.get('appID', '')
     isAddBourseMoney = GameWorld.ToIntDef(gmCmdDict.get('isAddBourseMoney', ''), 0)
@@ -69,7 +50,6 @@
     changeCoinPointBefore = curPlayer.GetChangeCoinPointTotal()
     bourseMoneyBefore = PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney)
     
-
     orderInfoIpyData = None
     if appID:
         orderInfoIpyData = IpyGameDataPY.GetIpyGameDataNotLog("OrderInfo", value, appID)
@@ -105,8 +85,7 @@
                   "bourseMoney":[bourseMoneyBefore, bourseMoneyAfter]}
     
     #流向 增加金额记录
-    DataRecordPack.DR_ToolGMOperate(playerID, curPlayer.GetPlayerName(), curPlayer.GetAccID(), 'GMT_CTG', resultDict)
+    DataRecordPack.DR_ToolGMOperate(playerID, curPlayer.GetPlayerName(), curPlayer.GetAccID(), GMT_Name, resultDict)
     
     return Result, resultDict
-    
-    
\ No newline at end of file
+ 
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py
index 24c9bd3..aebce44 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/GMToolLogicProcess/ProjSpecialProcess.py
@@ -41,6 +41,9 @@
 from Common import (CommFuncEx, mylog)
 
 from Protocol import (MMORPGPack, RecvPackProtocol, SendPackProtocol, MergeServerRecvProtocol, MergeServerSendProtocol)
+import PlayerOfflineSupport
+import PyGameData
+import GameWorld
       
 ################################################################## 
                 ####### python逻辑入口 ####### 
@@ -152,6 +155,58 @@
 
 ################################################################## 
 
+def GMCmdPlayerValidation(gmCmdDict, offlineSupport=True):
+    '''后台GM工具玩家命令通用验证
+    @param gmCmdDict: 命令参数字典
+    @param offlineSupport: 离线玩家是否支持该命令,默认支持,当玩家离线时,会在上线后执行该命令
+    @return: GMCommon.Def_xxx, curPlayer
+                                非 Def_Success 的错误类型        -    代表错误,可直接返回给后台
+            Def_Success, curPlayer    -    curPlayer为空时代表玩家离线状态
+    '''
+    
+    queryType = gmCmdDict.get(GMCommon.Def_GMKey_QueryType, '')
+    playerFind = gmCmdDict.get(GMCommon.Def_GMKey_PlayerFind, '')
+    
+    if len(playerFind) <= 0:
+        return GMCommon.Def_ParamErr, None
+    
+    # 玩家姓名
+    if queryType == GMCommon.Def_GMKey_PlayerName:
+        rec = PyGameData.g_usrCtrlDB.findDBPlayerByName(playerFind)
+    elif queryType == GMCommon.Def_GMKey_PlayerAccID:
+        rec = PyGameData.g_usrCtrlDB.findDBPlayerByAccID(playerFind)
+    else:
+        return GMCommon.Def_ParamErr, None
+    
+    if not rec:
+        # db找不到就是不存在该玩家
+        return GMCommon.Def_NoTag, None
+    
+    playerID = rec.get(u'PlayerID', 0)
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+    if not curPlayer or curPlayer.IsEmpty():
+        # 离线处理
+        if offlineSupport:
+            PlayerOfflineSupport.AddOfflineUnprocessed(playerID, "GMToolCMD", gmCmdDict)
+            return GMCommon.Def_Success, None
+        return GMCommon.Def_PlayerOfLine, None
+    
+    return GMCommon.Def_Success, curPlayer
+
+def GMCmdPlayerLogin(curPlayer):
+    PlayerOfflineSupport.DoOfflineUnprocessed(curPlayer, "GMToolCMD", __doOfflineGMToolCMD)
+    return
+
+def __doOfflineGMToolCMD(curPlayer, recData, eventName, eventData):
+    gmCmdDict = eventData
+    if not gmCmdDict or not isinstance(gmCmdDict, dict):
+        return
+    funcName = gmCmdDict.get(GMCommon.Def_GMKey_Type, '')  
+    callFunc = GetExecFunc(Commands, "%s.%s" % (funcName, "OnExec"))
+    if callFunc != None:
+        callFunc(gmCmdDict)
+    return
+
 
 ## gm命令执行
 #
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py
index f3e9f06..fdfb0ba 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py
@@ -415,12 +415,45 @@
         return
     
     def findDBPlayer(self, playerID):
+        '''根据玩家ID查找dbPlayer
+        @return: None or tagDBPlayer
+        '''
         col = self.db[UCN_DBPlayer]
         dbPlayer = DataServerPlayerData.tagDBPlayer()
         dbPlayer.IsDeleted = 0
         if not dbPlayer.adoLoadCEx(col, {"PlayerID":playerID}):
             return
         return dbPlayer
+    
+    def findDBPlayerByName(self, playerName, backDBPlayer=False):
+        '''根据玩家名查找dbPlayer
+        @param backDBPlayer: 可指定返回 tagDBPlayer 实例,默认false,直接返回db数据字典
+        @return: None or db数据字典{k:v, ...} or tagDBPlayer
+        '''
+        collection = self.db[UCN_DBPlayer]
+        rec = collection.find_one({'PlayerName':fix_incomingText(playerName), 'IsDeleted':0})
+        if not rec:
+            return
+        if backDBPlayer:
+            dbPlayer = DataServerPlayerData.tagDBPlayer()
+            dbPlayer.readRecord(rec)
+            return dbPlayer
+        return rec
+    
+    def findDBPlayerByAccID(self, accID, backDBPlayer=False):
+        '''根据玩家账号查找dbPlayer
+        @param backDBPlayer: 可指定返回 tagDBPlayer 实例,默认false,直接返回db数据字典
+        @return: None or db数据字典{k:v, ...} or tagDBPlayer
+        '''
+        collection = self.db[UCN_DBPlayer]
+        rec = collection.find_one({'AccID':fix_incomingText(accID), 'IsDeleted':0})
+        if not rec:
+            return
+        if backDBPlayer:
+            dbPlayer = DataServerPlayerData.tagDBPlayer()
+            dbPlayer.readRecord(rec)
+            return dbPlayer
+        return rec
     
     def requestLogicProcess(self, pack):
         db = self.db
@@ -899,7 +932,10 @@
         self.packSend(sessionID, 0, 0, CommonDefine.atMergeLogic, MMORPGPack.stGame,
                       MMORPGPack.stData, sendPack.GetBuffer())
     
-
+    def OnPlayerLogin(self, curPlayer):
+        ProjSpecialProcess.GMCmdPlayerLogin(curPlayer)
+        return
+    
     def OnGMToolCommand(self, db, pack):
 
         if CommonDefine.IsDebug():
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index ba190b1..edb33eb 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -1384,7 +1384,8 @@
                        Def_GameRecType_FamilyGCZJoinMember, # 仙盟攻城战参与成员信息, zoneID 304
                        Def_GameRecType_FamilyGCZCityWall, # 仙盟攻城战城池信息, zoneID 305
                        Def_GameRecType_TalkCache, # 聊天缓存,频道 306
-                       ) = range(300, 1 + 306)
+                       Def_GameRecType_PlayerOfflineUnprocessed, # 离线玩家待处理事件,playerID 307
+                       ) = range(300, 1 + 307)
 #通用信息记录新 - 字典key配置,如果有配置,则可额外按对应记录Value值存储字典,方便快速取值,可配置Value编号 1~8,配空默认 Value1
 Def_GameRecValueKeyDict = {
                            Def_GameRecType_Xiangong:[1],

--
Gitblit v1.8.0