ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
@@ -15,16 +15,26 @@
#"""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 GameWorldAction
import PlayerViewCache
import PlayerControl
import NetPackCommon
import PlayerOnline
import ShareDefine
import PlayerTeam
import PyGameData
import BattleObj
import ChPlayer
import ObjPool
import datetime
import time
@@ -65,21 +75,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)
@@ -93,17 +113,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):
@@ -228,15 +274,32 @@
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)
    
@@ -246,6 +309,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()
@@ -258,17 +336,60 @@
    DoCheckNewServerOpen(tick)
    DBDataMgr.OnMinute(curTime)
    DoLogic_GameWorldEvenByTime(tick)
    GameWorldAction.OnProcessGameAction(curTime)
    
    #每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 OnGM_CrossCenterEvent(gmEvent):
    if not GameWorld.IsCrossCenter():
        return
    serverEventValue = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_CrossCenterEvent)
    if DoLogic_CrossCenterEvent(serverEventValue, gmEvent=gmEvent):
        CrossMgr.SendCrossServerEvent(gmEvent=gmEvent)
    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
@@ -318,11 +439,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
@@ -344,6 +467,74 @@
    PlayerEventCounter.DoLogic_OnYear(tick)
    return
def DoLogic_CrossCenterEvent(centerEventValue, centerServerID=0, gmEvent=""):
    ## 收到跨服中心事件同步,如OnDay等
    serverEventValue = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_CrossCenterEvent)
    if not serverEventValue:
        serverEventValue = centerEventValue
        DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_CrossCenterEvent, centerEventValue)
    if serverEventValue == centerEventValue and not gmEvent:
        if centerServerID:
            GameWorld.Log("本服与跨服中心事件值相同不处理! serverEventValue=%s,centerEventValue=%s,centerServerID=%s" % (serverEventValue, centerEventValue, centerServerID))
        return
    if centerServerID:
        GameWorld.Log("本服与跨服中心事件值变化! serverEventValue=%s,centerEventValue=%s,centerServerID=%s,gmEvent=%s" % (serverEventValue, centerEventValue, centerServerID, gmEvent))
    else:
        GameWorld.Log("跨服中心服务器事件值变化! serverEventValue=%s,centerEventValue=%s,gmEvent=%s" % (serverEventValue, centerEventValue, gmEvent))
    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 or gmEvent == "GMOnHour"):
        isEvent = True
        PlayerEventCounter.DoLogic_CrossCenterOnHour(centerEventValue)
    #OnDay事件
    if (serverDay != centerDay or serverMonth != centerMonth or serverYear != centerYear or gmEvent == "GMOnDay"):
        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)
    # 游戏服额外处理玩家
    if GameWorld.IsMainServer():
        playerManager = GameWorld.GetPlayerManager()
        for i in xrange(playerManager.OnlineCount()):
            curPlayer = playerManager.OnlineAt(i)
            if not GameWorld.IsNormalPlayer(curPlayer):
                continue
            PlayerEventCounter.PlayerOnCrossCenterEvent(curPlayer, centerEventValue, gmEvent=gmEvent)
    return isEvent
def __CheckIpyDataRecycle(timeNow):
    ## 检查IpyData数据回收