hxp
4 天以前 c3bbd3b0263fc6c2127cd9f072f497f46f98758b
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
@@ -15,14 +15,25 @@
#"""Version = 2025-05-15 10:35"""
#-------------------------------------------------------------------------------
import CrossMgr
import ChConfig
import DBDataMgr
import GameWorld
import PyMongoMain
import PlayerFamily
import IpyGameDataPY
import IPY_GameWorld
import DataRecordPack
import PlayerEventCounter
import ShareDefine
import PlayerTeam
import PyGameData
import PlayerViewCache
import PlayerControl
import NetPackCommon
import PlayerOnline
import ShareDefine
import PyGameData
import BattleObj
import ChPlayer
import ObjPool
import datetime
import time
@@ -63,21 +74,31 @@
#调用该函数时,C++已经设置好区服,如果改变区服需重启
def StartDB(tick):
    #初始化数据库, 恢复备档(按区服记录), 加载静态表
    from PyMongoDB import PyMongoMain
    #from PyMongoDB import PyMongoMain
    PyMongoMain.StartDB()
    InitGameWorld(tick)
    return
def InitGameWorld(tick):
    ## GameWorld初始化
    if PyGameData.g_initGameTime:
    if PyGameData.g_initGameWorldOK:
        return
    serverID = GameWorld.GetGameWorld().GetServerID()
    GameWorld.Log("服务器启动初始化InitGameWorld: serverID=%s" % serverID)
    serverType = GameWorld.GetServerType()
    GameWorld.Log("服务器启动初始化InitGameWorld: serverID=%s,serverType=%s" % (serverID, serverType))
    DBDataMgr.OnServerStart() # 优先加载公共数据
    #ItemCommon.InitPyItem() # 改为放 InitItem 加载
    LoadDBPlayer()
    PlayerViewCache.LoadRobot()
    PyGameData.g_initGameTime = int(time.time()) # 放到加载数据之后
    
    # 检查跨服中心唯一性
    GameWorld.CheckCrossCenterUniquenessErr()
    if DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_FamilyTransDataTime):
        DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_FamilyTransDataTime, 0)
        GameWorld.Log("启动服务器时重置跨服公会传输数据状态!")
    #初始话开服时间、星期几
    initOpenServerTime = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_InitOpenServerTime)
    openServerWeekday = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_OpenServerWeekday)
@@ -91,17 +112,43 @@
    # 其他功能初始化
    
    
    # 最后触发检查是否完全启动成功
    PyGameData.g_initGameWorldOK = True
    OnServerInitOK()
    return
def OnServerInitOK():
    '''服务器完全启动初始化成功后的处理,如db数据加载及静态物品数据等都加载完毕了
    如跨服间相关逻辑通讯需要等服务器完全启动完毕后才可进行
    '''
    if not PyGameData.g_initGameWorldOK or not PyGameData.g_initPyItem:
        return
    if PyGameData.g_serverInitOK:
        return
    PyGameData.g_serverInitOK = True
    tick = GameWorld.GetGameWorld().GetTick()
    serverID = GameWorld.GetGameWorld().GetServerID()
    OnHighProcess(tick) # 主动触发一次高精度的调用,确保服务器启动后一些功能活动等的数据会被加载
    OnMinute(tick)
    
    GameWorld.Log("=============================== 服务器启动成功 ===================================")
    serverType = GameWorld.GetServerType()
    isCrossServer = GameWorld.IsCrossServer()
    if isCrossServer:
        pass
        GameWorld.Log("跨服服务器启动成功: serverType=%s,serverID=%s" % (serverType, serverID))
    else:
        serverGroupID = GameWorld.GetServerGroupID()
        GameWorld.Log("服务器启动成功: ServerGroupID=%s,serverID=%s" % (serverGroupID, serverID))
    PyGameData.g_serverInitOK = True
        serverDay = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_ServerDay) + 1
        isMixServer = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_IsMixServer)
        mixServerDay = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_MixServerDay) + 1
        GameWorld.Log("游戏服务器启动成功: serverType=%s,serverID=%s,serverDay=%s,isMixServer=%s,mixServerDay=%s"
                      % (serverType, serverID, serverDay, isMixServer, mixServerDay))
    DataRecordPack.DR_Reload("restart")
    # ---------- 以下处理服务器完全启动好后的逻辑 ----------
    return
def AllMapServerInitOK(tick):
@@ -226,11 +273,33 @@
def OnHighProcess(tick):
    ## 每秒分钟执行一次
    if not PyGameData.g_initGameTime:
    if not PyGameData.g_serverInitOK:
        return
    if tick - PyGameData.g_highProcessTick < 1000:
    curTime = int(time.time())
    if not PyGameData.g_highProcessTime:
        PyGameData.g_highProcessTime = curTime
    if curTime < PyGameData.g_highProcessTime:
        GameWorld.Log("时间回调了: lastProcessTime=%s" % (GameWorld.ChangeTimeNumToStr(PyGameData.g_highProcessTime)))
        PyGameData.g_highProcessTime = curTime
        OnFixServerTimeProcess()
    passSeconds = curTime - PyGameData.g_highProcessTime
    if passSeconds < 1:
        return
    PyGameData.g_highProcessTick = tick
    if passSeconds > 10:
        GameWorld.Log("时间误差过大: passSeconds=%s,lastProcessTime=%s" % (passSeconds, GameWorld.ChangeTimeNumToStr(PyGameData.g_highProcessTime)))
        OnFixServerTimeProcess()
    PyGameData.g_highProcessTime = curTime
    if PyGameData.g_serverClosing:
        CheckCloseMapOK()
        return
    PyMongoMain.GetUserCtrlDB().onSecondProcess()
    CrossMgr.OnSecondProcess(tick, curTime)
    OnMinute(tick)
    
    # 其他逻辑
@@ -239,6 +308,21 @@
    
    return
def OnFixServerTimeProcess():
    # 补同步一次服务器时间给前端
    playerManager = GameWorld.GetPlayerManager()
    for i in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(i)
        if not GameWorld.IsNormalPlayer(curPlayer):
            continue
        ChPlayer.Sync_PyServerDataTimeToClient(curPlayer)
        ChPlayer.Sync_OpenServerDay(curPlayer)
    return
def OnMinute(tick):
    ## 每整分钟执行一次
    curTime = GameWorld.GetCurrentTime()
@@ -252,16 +336,53 @@
    DBDataMgr.OnMinute(curTime)
    DoLogic_GameWorldEvenByTime(tick)
    
    #每5分钟
    if curMinute % 5 == 0:
        OnMinute_5(curTime, tick)
    #其他功能逻辑
    #GameWorldActionControl.Dispose_OperationActionState()
    #GameWorldActionControl.Dispose_DailyActionState()
    #GameWorldActionControl.Dispose_FBStateTime()
    PlayerControl.OnMinute(curTime)
    PlayerFamily.OnMinute()
    PlayerOnline.OnMinute()
    BattleObj.OnMinute()
    ObjPool.OnMinute(curTime)
    
    PlayerTeam.OnCheckTeamPlayerDisconnectTimeout(tick)
    __CheckIpyDataRecycle(curTime)
    return
    
def OnMinute_5(curTime, tick):
    ## 每5分钟
    DisposeGameActivePlayer(curTime, tick)
    return
def DisposeGameActivePlayer(curTime, tick):
    curMinute = curTime.minute
    gameWorld = GameWorld.GetGameWorld()
    noteData = gameWorld.GetGameWorldDictByKey("OnlineCntM")
    if noteData == curMinute:
        # 同一分钟只处理1次
        return
    gameWorld.SetGameWorldDict("OnlineCntM", curMinute)
    activePlayerCount = GameWorld.GetPlayerManager().OnlineCount()
    DataRecordPack.DR_OnLinePlayerCount(activePlayerCount) # 总在线
    return
def DoLogic_GameWorldEvenByTime(tick):
    '''跨服事件由跨服中心服务器驱动,游戏服使用原方式
    跨服中心OnEvent -> 其他服务器OnEvent (包含个常规跨服服务器及游戏服,不保证谁先执行)
        个别功能如果需要确保跨服先执行Event,再处理游戏服Event,可以由功能驱动跨服先执行,再同步游戏服执行
    '''
    if GameWorld.IsCrossServer():
        if not GameWorld.IsCrossCenter():
            return
        eventValue = GameWorld.ToIntDef(GameWorld.ChangeTimeNumToStr(int(time.time()), ChConfig.TYPE_Time_Format_YmdH))
        if DoLogic_CrossCenterEvent(eventValue):
            CrossMgr.SendCrossServerEvent()
        return
    #-----------服务器当前时间
    curTime = datetime.datetime.today()
    curTimeHour = curTime.hour
@@ -311,11 +432,13 @@
    GameWorld.Log("Server -> OnDay!")
    #设定服务器当前天事件
    eventMgr = DBDataMgr.GetEventTrigMgr()
    eventMgr.SetValueIncrement(ShareDefine.Def_ServerDay)
    serverDay = eventMgr.SetValueIncrement(ShareDefine.Def_ServerDay)
    isMixServer = eventMgr.GetValue(ShareDefine.Def_IsMixServer)
    mixServerDay = 0
    if isMixServer:
        eventMgr.SetValueIncrement(ShareDefine.Def_MixServerDay)
        mixServerDay = eventMgr.SetValueIncrement(ShareDefine.Def_MixServerDay)
    GameWorld.Log("OnDay -> serverDay=%s,isMixServer=%s,mixServerDay=%s" % (serverDay + 1, isMixServer, mixServerDay + 1))
    PlayerEventCounter.DoLogic_OnDay(tick)
    return
@@ -337,6 +460,65 @@
    PlayerEventCounter.DoLogic_OnYear(tick)
    return
def DoLogic_CrossCenterEvent(centerEventValue, centerServerID=0):
    ## 收到跨服中心事件同步,如OnDay等
    serverEventValue = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_CrossCenterEvent)
    if not serverEventValue:
        serverEventValue = centerEventValue
        DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_CrossCenterEvent, centerEventValue)
    if serverEventValue == centerEventValue:
        if centerServerID:
            GameWorld.Log("本服与跨服中心事件值相同不处理! serverEventValue=%s,centerEventValue=%s,centerServerID=%s" % (serverEventValue, centerEventValue, centerServerID))
        return
    if centerServerID:
        GameWorld.Log("本服与跨服中心事件值变化! serverEventValue=%s,centerEventValue=%s,centerServerID=%s" % (serverEventValue, centerEventValue, centerServerID))
    else:
        GameWorld.Log("跨服中心服务器事件值变化! serverEventValue=%s,centerEventValue=%s" % (serverEventValue, centerEventValue))
    serverEventTime = GameWorld.ChangeStrToDatetime("%s" % serverEventValue, ChConfig.TYPE_Time_Format_YmdH)
    centerEventTime = GameWorld.ChangeStrToDatetime("%s" % centerEventValue, ChConfig.TYPE_Time_Format_YmdH)
    serverHour = serverEventTime.hour
    serverDay = serverEventTime.day
    #serverWeek = datetime.datetime.isocalendar(serverEventTime)[1]
    serverMonth = serverEventTime.month
    serverYear = serverEventTime.year
    centerHour = centerEventTime.hour
    centerDay = centerEventTime.day
    #centerWeek = datetime.datetime.isocalendar(centerEventTime)[1]
    centerMonth = centerEventTime.month
    centerYear = centerEventTime.year
    DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_CrossCenterEvent, centerEventValue)
    isEvent = False
    #OnHour事件
    if (serverHour != centerHour or serverDay != centerDay or serverMonth != centerMonth or serverYear != centerYear):
        isEvent = True
        PlayerEventCounter.DoLogic_CrossCenterOnHour(centerEventValue)
    #OnDay事件
    if (serverDay != centerDay or serverMonth != centerMonth or serverYear != centerYear):
        isEvent = True
        PlayerEventCounter.DoLogic_CrossCenterOnDay(centerEventValue)
    #OnWeek事件
    #if (serverWeek != curTimeWeek):
    #    OnWeek(tick)
    #OnMonth事件
    #if (serverMonth != curTimeMonth or serverYear != curTimeYear):
    #    OnMonth(tick)
    #OnYear事件
    #if serverYear != curTimeYear:
    #    OnYear(tick)
    return isEvent
def __CheckIpyDataRecycle(timeNow):
    ## 检查IpyData数据回收
@@ -367,15 +549,43 @@
# 关闭地图通知py处理
def CloseMap(tick):
    serverID = GameWorld.GetGameWorld().GetServerID()
    GameWorld.Log("地图服务器关闭开始保存数据! serverID=%s" % serverID)
    PyGameData.g_serverClosing = 1
    playerManager = GameWorld.GetPlayerManager()
    for i in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(i)
        if not curPlayer or curPlayer.GetID() == 0 or curPlayer.IsEmpty():
            continue
        #镜像玩家回收、真实玩家踢下线
        if GameWorld.IsMirrorPlayer(curPlayer):
            PlayerControl.DeleteMirror(curPlayer)
        else:
            curPlayer.Kick(IPY_GameWorld.disMapServerClose)
    DBDataMgr.OnServerClose()
    return
def CheckCloseMapOK():
    '''检查等待关服数据处理完毕
    没有玩家了,且公共数据已入库完毕
    '''
    if PyGameData.g_serverClosing != 1:
        return
    if not PyGameData.g_closeSaveDataOK:
        return
    if GameWorld.GetPlayerManager().OnlineCount():
        return
    DBDataMgr.ClearBackupFile() # 正常关服数据处理完毕可直接删除备档
    from PyMongoDB.DBCommon import CommonDefine
    from PyMongoDB.Common import CommFunc
    #初始化数据库, 恢复备档(按区服记录), 加载静态表
    try:
        pass
    finally:
        #回发地图 处理完成,必须被调用地图才能正常关闭
        data = ''
        data = CommFunc.WriteBYTE(data, CommonDefine.dgPlayerSaveGameServerData)
        NetPackCommon.SendPyPackToMapServerSelf(data, len(data))
        GameWorld.Log("python 已处理地图关闭逻辑")
    return
    data = ''
    data = CommFunc.WriteBYTE(data, CommonDefine.dgPlayerSaveGameServerData)
    NetPackCommon.SendPyPackToMapServerSelf(data, len(data))
    GameWorld.Log("python 已处理地图关闭逻辑")
    PyGameData.g_serverClosing = 2
    return