From f2cf64ffabcd15d5497aee8914b8d37d8b9a88b0 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期六, 07 二月 2026 15:39:43 +0800
Subject: [PATCH] 66 【公会】基础主体-服务端(公会GM命令支持跨服 CreateFamily、Family、Zhenbaoge;跨服公会聊天支持,包含公会聊天缓存;查看玩家A705回包增加公会所在服务器ID信息;)
---
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py | 264 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 237 insertions(+), 27 deletions(-)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
index 318d0f4..08e4dfb 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
+++ b/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
\ No newline at end of file
+ data = ''
+ data = CommFunc.WriteBYTE(data, CommonDefine.dgPlayerSaveGameServerData)
+ NetPackCommon.SendPyPackToMapServerSelf(data, len(data))
+ GameWorld.Log("python 已处理地图关闭逻辑")
+ PyGameData.g_serverClosing = 2
+ return
+
\ No newline at end of file
--
Gitblit v1.8.0