From 4e6d5af98a0e0810ddfe2cc0faaec2832f865bd6 Mon Sep 17 00:00:00 2001 From: hch <305670599@qq.com> Date: 星期二, 20 五月 2025 15:23:30 +0800 Subject: [PATCH] 15 卡牌服务端搭建 - 地图增加FindStr接口;玩家下线保存,python增加MapCallDB调用DB逻辑 --- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py | 15 +++ ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IPY_GameWorld1.py | 1 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py | 16 ++-- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py | 186 ++++++++++++++------------------------------- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py | 12 +++ 5 files changed, 94 insertions(+), 136 deletions(-) diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IPY_GameWorld1.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IPY_GameWorld1.py index 962b03e..f6ad5d3 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IPY_GameWorld1.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IPY_GameWorld1.py @@ -439,6 +439,7 @@ def GetActiveEventCount(self): return _IPY_GameWorld1.IPY_GameWorld_GetActiveEventCount(self) def GetActiveEventByIndex(self, *args): return _IPY_GameWorld1.IPY_GameWorld_GetActiveEventByIndex(self, *args) def DataServer_Rec(self, *args): return _IPY_GameWorld1.IPY_GameWorld_DataServer_Rec(self, *args) + def FindStr(self, *args): return _IPY_GameWorld1.IPY_GameWorld_FindStr(self, *args) def SetTickTypeCount(self, *args): return _IPY_GameWorld1.IPY_GameWorld_SetTickTypeCount(self, *args) def GetTickByType(self, *args): return _IPY_GameWorld1.IPY_GameWorld_GetTickByType(self, *args) def SetTickByType(self, *args): return _IPY_GameWorld1.IPY_GameWorld_SetTickByType(self, *args) 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 5eb0616..09f53f7 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py @@ -175,11 +175,15 @@ import PlayerMail import DBDataMgr import GameServerRefresh +import IPY_ServerDefine +import CommFunc +from PyMongoDB import RecvPackToMapDB import datetime import time import math import re +import base64 #--------------------------------------------------------------------- #--------------------------------------------------------------------- @@ -3113,10 +3117,19 @@ except: import traceback GameWorld.RaiseException("玩家下线逻辑错误\r\n%s" % traceback.format_exc()) - + RecvPackToMapDB.MapCallDB(GetPackSaveData(curPlayer)) #调用底层使玩家下线 curPlayer.DoDisconnect(tick) +# 简化c++的保存数据封包 +def GetPackSaveData(curPlayer): + roleSaveData = base64.b64decode(curPlayer.GetPackData()) # base64加密了 + allData = "" + allData = CommFunc.WriteBYTE(allData, IPY_ServerDefine.gstUpdate) + allData = CommFunc.WriteString(allData, len(roleSaveData), roleSaveData) + return allData + + ##玩家正常下线 #@param curPlayer 玩家索引 #@param tick 时间戳 diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py index 94eeee2..98b53fa 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameServerRefresh.py @@ -340,15 +340,15 @@ # @return None # @remarks 函数详细说明. def GameServer_PlayerSave(index, tick): - curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) - #2009-07-04 因地图服务器有可能关闭重开,这里要判定空 - if not curPlayer: - return + # curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + # #2009-07-04 因地图服务器有可能关闭重开,这里要判定空 + # if not curPlayer: + # return - # 1为保存 0为正常下线 - curPlayer.SetCountryLastWeekHornor(1) # 利用此字段通知为保存数据,非下线数据 - curPlayer.PushSaveData() - curPlayer.SetCountryLastWeekHornor(0) # 利用此字段通知为保存数据,非下线数据 + # # 1为保存 0为正常下线 + # curPlayer.SetCountryLastWeekHornor(1) # 利用此字段通知为保存数据,非下线数据 + # curPlayer.PushSaveData() + # curPlayer.SetCountryLastWeekHornor(0) # 利用此字段通知为保存数据,非下线数据 return #=============================================================================== 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 7ea3eda..6459dcf 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 @@ -556,19 +556,13 @@ oFuncGrade.End() return True if requestType == CommonDefine.gstUpdate: - if DBConfig.IsOpenDbSaveServer: - msg = error.formatMsg('DeployError', error.ERROR_NO_56, "DbSaveServer is open, type = %d request should be send to PyMongoDBSaveServer"%CommonDefine.gstUpdate) - mylog.DeployError(msg, True) - return False - oFuncGrade = self.GetFuncGrade("gstUpdate") oFuncGrade.Start() if self.IsMergeServer(): - if not self.onSaveMapServerPlayerDataMergeServer(db, pack): - mylog.error("onSaveMapServerPlayerDataMergeServer failed!sessionID = 0x%X", pack.getPackHead().sessionID) + self.onSaveMapServerPlayerDataMergeServer(db, pack) else: - if not self.onSaveMapServerPlayerData(db, pack): - mylog.error("onSaveMapServerPlayerData failed!sessionID = 0x%X", pack.getPackHead().sessionID) + self.onSaveMapServerPlayerData(db, pack) + oFuncGrade.End() return True if requestType == CommonDefine.gstSavePlayerInfo: @@ -1506,124 +1500,62 @@ g_mergeRegisterPlayerDict = PyGameData.g_mergeRegisterPlayerDict '''玩家下线,跨服服务器下线不保存''' pos = 1 #跳过gstUpdate - buf = pack.getBuffer() - length = pack.getLength() - type, pos = CommFunc.ReadBYTE(buf, pos) - if type == CommonDefine.gstPlayerDetail: - needReturn, pos = CommFunc.ReadBYTE(buf, pos) - packCrcPos = pos - packCrc, pos = CommFunc.ReadDWORD(buf, pos) - serverTypePos = pos - serverType, pos = CommFunc.ReadBYTE(buf, pos) - if serverType == MMORPGPack.stMin: - #其他服务器未发现异常,检查CRC - saveData, pos = CommFunc.ReadString(buf, pos, length - pos) - calcCrc = CommFunc.ToDWORD(crc32(saveData)) - if not packCrc == calcCrc: - #CRC校验错误 - serverTypeData = chr(MMORPGPack.stData) - buf = buf[:serverTypePos] + serverTypeData+ buf[(serverTypePos + 1):] - self.onSavePlayerDataCRCError(db, pack, buf[packCrcPos:]) - return (False, 0) - else: - pass #正常情况 - else: - self.onSavePlayerDataCRCError(db, pack, buf[packCrcPos:]) - return (False,0) + saveData, pos = CommFunc.ReadString(pack.getBuffer(), pos, pack.getLength() - pos) + + + # 与策划约定 离线超过3分钟则必须从子服再次登录汇报新数据 + # 为了避免 g_mergeRegisterPlayerDict 占用过多内存,每10分钟清除一次已下线数据 + result, playerID, accID = self.__ReadPlayerID(db, saveData) + + # 保存跨服数据主要是为了避免短时间断线重连玩家数据不对应,如坐标又回到了起点 + if accID in g_mergeRegisterPlayerDict: + g_mergeRegisterPlayerDict[accID][MergeRegPInfoIndex_LogoutTime] = time() + g_mergeRegisterPlayerDict[accID][MergeRegPInfoIndex_PackData].Data = saveData + g_mergeRegisterPlayerDict[accID][MergeRegPInfoIndex_PackData].DataLen = len(saveData) - # 与策划约定 离线超过3分钟则必须从子服再次登录汇报新数据 - # 为了避免 g_mergeRegisterPlayerDict 占用过多内存,每10分钟清除一次已下线数据 - result, playerID, accID = self.__ReadPlayerID(db, saveData) - - # 保存跨服数据主要是为了避免短时间断线重连玩家数据不对应,如坐标又回到了起点 - if accID in g_mergeRegisterPlayerDict: - g_mergeRegisterPlayerDict[accID][MergeRegPInfoIndex_LogoutTime] = time() - g_mergeRegisterPlayerDict[accID][MergeRegPInfoIndex_PackData].Data = saveData - g_mergeRegisterPlayerDict[accID][MergeRegPInfoIndex_PackData].DataLen = len(saveData) - - mylog.info("onSaveMapServerPlayerDataMergeServer result = %s, playerID = %s, sessionID = 0x%X" - % (result, playerID, pack.getPackHead().sessionID)) - #回报 - if needReturn: - updateReturn = SendPackProtocol.tagDBUpdateReturn() - updateReturn.CallType = CommonDefine.dgUpDate - updateReturn.UpdateType = CommonDefine.gstPlayerDetail - updateReturn.Result = result - updateReturn.PlayerID = playerID - self.sendString(pack, updateReturn.GetBuffer()) - return (result, playerID) + mylog.info("onSaveMapServerPlayerDataMergeServer result = %s, playerID = %s" % (result, playerID)) + + return (result, playerID) def onSaveMapServerPlayerData(self, db, pack): '''玩家下线,保存玩家在MapServer的数据''' pos = 1 #跳过gstUpdate - buf = pack.getBuffer() - length = pack.getLength() - type, pos = CommFunc.ReadBYTE(buf, pos) - if type == CommonDefine.gstPlayerDetail: - needReturn, pos = CommFunc.ReadBYTE(buf, pos) - packCrcPos = pos - packCrc, pos = CommFunc.ReadDWORD(buf, pos) - serverTypePos = pos - serverType, pos = CommFunc.ReadBYTE(buf, pos) - if serverType == MMORPGPack.stMin: - #其他服务器未发现异常,检查CRC - saveData, pos = CommFunc.ReadString(buf, pos, length - pos) - calcCrc = CommFunc.ToDWORD(crc32(saveData)) - if not packCrc == calcCrc: - #CRC校验错误 - serverTypeData = chr(MMORPGPack.stData) - buf = buf[:serverTypePos] + serverTypeData+ buf[(serverTypePos + 1):] - self.onSavePlayerDataCRCError(db, pack, buf[packCrcPos:]) - return (False, 0) - else: - pass #正常情况 - else: - self.onSavePlayerDataCRCError(db, pack, buf[packCrcPos:]) - return (False,0) - #正常情况 - #保存数据 - result = False - playerID = 0 - if DBConfig.PackSave: - result, playerID, accID = self.SavePlayerMapServerDataEx(db, saveData) - else: - result, playerID, accID = self.SavePlayerMapServerData(db, saveData) - if not result: - #保存失败 - sessionID = pack.getPackHead().sessionID - msg = error.formatMsg('error', error.ERROR_NO_59, 'Player save data failed!sessionID = %s'%sessionID) - mylog.error(msg) - - DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\SaveFailDump', '%s.mdat'%sessionID, buf[pos:]) -# self.sendString(pack, updateReturn.GetBuffer()) -# return - #回报 - if needReturn: - updateReturn = SendPackProtocol.tagDBUpdateReturn() - updateReturn.CallType = CommonDefine.dgUpDate - updateReturn.UpdateType = CommonDefine.gstPlayerDetail - updateReturn.Result = result - updateReturn.PlayerID = playerID - self.sendString(pack, updateReturn.GetBuffer()) - - # 玩家下线恢复充值兑换中的订单,IsProcee为1,但endtime为空的情况 - self.RevoverBillProcess(db, accID) - mylog.info("onSaveMapServerPlayerData result = %s, playerID = %s, sessionID = 0x%X"%(result, playerID, pack.getPackHead().sessionID)) + saveData, pos = CommFunc.ReadString(pack.getBuffer(), pos, pack.getLength() - pos) + + #正常情况 + #保存数据 + result = False + playerID = 0 + if DBConfig.PackSave: + result, playerID, accID = self.SavePlayerMapServerDataEx(db, saveData) + else: + result, playerID, accID = self.SavePlayerMapServerData(db, saveData) + if not result: + #保存失败 + msg = error.formatMsg('error', error.ERROR_NO_59, 'Player save data failed!playerID = %s'%playerID) + mylog.error(msg) - # 下线成功入库后同步移动玩家备档备份文件夹 - PlayerBakDir = os.path.join(DBConfig.PlayerBakRoot, str(playerID)) - if os.path.exists(PlayerBakDir): - BakCopyDir = os.path.join(PlayerBakDir, "Backup") - for filename in os.listdir(PlayerBakDir): - if not filename.endswith(DBConfig.PlayerBakFileType): - continue - fullPath = os.path.join(PlayerBakDir, filename) - if not os.path.exists(os.path.join(BakCopyDir, filename)): - shutil.move(fullPath, BakCopyDir) - else: - os.remove(fullPath) - - return (result, playerID) + DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\SaveFailDump', '%s.mdat'%playerID, saveData) + + + # 玩家下线恢复充值兑换中的订单,IsProcee为1,但endtime为空的情况 + self.RevoverBillProcess(db, accID) + mylog.info("onSaveMapServerPlayerData result = %s, playerID = %s"%(result, playerID)) + + # 下线成功入库后同步移动玩家备档备份文件夹 + PlayerBakDir = os.path.join(DBConfig.PlayerBakRoot, str(playerID)) + if os.path.exists(PlayerBakDir): + BakCopyDir = os.path.join(PlayerBakDir, "Backup") + for filename in os.listdir(PlayerBakDir): + if not filename.endswith(DBConfig.PlayerBakFileType): + continue + fullPath = os.path.join(PlayerBakDir, filename) + if not os.path.exists(os.path.join(BakCopyDir, filename)): + shutil.move(fullPath, BakCopyDir) + else: + os.remove(fullPath) + + return (result, playerID) def __PlayerBackupSave(self): db = self.db @@ -2187,12 +2119,12 @@ if self.updatePlayerAccState(db, playerRec.PlayerID, CommonDefine.pysForbidden): #封号成功,记录封号日志 self.sendAccForbiddenLogReq(playerRec.AccID, 1) - #回报保存失败 - updateReturn = SendPackProtocol.tagDBUpdateReturn() - updateReturn.CallType = CommonDefine.dgUpDate - updateReturn.UpdateType = CommonDefine.gstPlayerDetail - updateReturn.Result = 0 - self.sendString(pack, updateReturn.GetBuffer()) + # #回报保存失败 + # updateReturn = SendPackProtocol.tagDBUpdateReturn() + # updateReturn.CallType = CommonDefine.dgUpDate + # updateReturn.UpdateType = CommonDefine.gstPlayerDetail + # updateReturn.Result = 0 + # self.sendString(pack, updateReturn.GetBuffer()) def sendAccForbiddenLogReq(self, accid, isForbidden): return diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py index 5e831b5..5748da7 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py @@ -12,6 +12,7 @@ import PyGameData import GameWorld +# C++调用 用封包格式 通知map处理DB数据 def RecvPackToMapDB(packBuff): pack = MMORPGPack.MMORPGPacket() pack.readData(packBuff) @@ -25,4 +26,15 @@ return False #GameWorld.Log("RecvPackToMapDB packlen %s"%len(packBuff)) + PyGameData.g_usrCtrlDB.requestLogicProcess(pack) + + +# 地图自己调用处理DB数据,不一定要符合封包格式,PY根据功能自定义组成封包 +def MapCallDB(packBuff, isBuffer = True): + pack = MMORPGPack.MMORPGPacket() + if isBuffer: + pack.setBuffer(packBuff) # 只设置数据 + else: + pack.readData(packBuff) # 设置封包头 和 数据 + PyGameData.g_usrCtrlDB.requestLogicProcess(pack) \ No newline at end of file -- Gitblit v1.8.0