From 84ede803777ff10b5cbe93b1ec0168af08f55d5e Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 13 一月 2021 18:11:26 +0800
Subject: [PATCH] 8677 【BT】【后端】跨服冲榜活动; 新增跨服活动时间管理模块、跨服榜单;跨服邮件;跨服广播优化;相关GM命令、后台工具;
---
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py | 73 +
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossActCTGBillboard.py | 288 ++++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py | 60
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py | 669 +++++++++
ServerPython/CoreServerGroup/GameServer/Script/GM/GMShell.py | 25
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py | 34
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py | 3
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py | 60
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py | 669 +++++++++
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py | 2
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py | 55
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py | 523 +++++++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py | 6
PySysDB/PySysDBPY.h | 21
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActCTGBillboard.py | 100 +
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py | 232 +++
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini | 11
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py | 37
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py | 3
ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py | 251 +++
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py | 5
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py | 37
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardDataCross.py | 107 +
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py | 18
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_CrossActServerIDChange.py | 170 ++
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py | 27
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_QueryBillboardCross.py | 88 +
ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py | 4
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py | 552 +++++++
PySysDB/PySysDBG.h | 27
30 files changed, 4,131 insertions(+), 26 deletions(-)
diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index 2192bf8..66f15ab 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -757,6 +757,33 @@
WORD LVLimit; //限制等级
};
+//跨服充值排行活动时间表
+
+struct tagCrossActCTGBillboard
+{
+ DWORD _CfgID; //配置ID
+ char ActGroupName; //活动组名(同组活动的名字需相同)
+ list ServerIDRangeList; //活动的账号服务器ID范围列表 [[serverIDA, serverIDB], ...]
+ char StartDate; //开启日期
+ char EndDate; //结束日期
+ dict NotifyInfoStart; //全服提示信息 - 相对开始时间
+ dict NotifyInfoEnd; //全服提示信息 - 相对结束时间
+ list NotifyInfoLoop; //全服提示信息 - 循环广播[循环分钟, 广播key, [广播参数列表可选]]
+ BYTE IsDayReset; //是否每天重置
+ list TemplateIDList; //模板ID列表
+};
+
+//跨服充值排行模板名次奖励表
+
+struct tagCrossActCTGBillboardOrder
+{
+ DWORD _TemplateID; //模板ID
+ WORD OrderA; //名次A
+ WORD OrderB; //至名次B
+ DWORD CTGAtleast; //至少充值RMB
+ list AwardItemList; //奖励物品列表[[物品ID,个数,是否拍品], ...]
+};
+
//装备升星表
struct tagEquipStarUp
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index d2b8d44..41ecc05 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1930,6 +1930,27 @@
DWORD Weight; //权重
};
+//跨服充值排行模板达标奖励表
+
+struct tagCrossActCTGBillboardDabiao
+{
+ DWORD _TemplateID; //模板ID
+ DWORD CTGNeed; //需充值RMB
+ BYTE AwardIndex; //奖励记录索引,从0开始,同个模板不可重复,不可变更
+ list AwardItemList; //奖励物品列表[[物品ID,个数,是否拍品], ...]
+};
+
+//跨服充值排行模板名次奖励表
+
+struct tagCrossActCTGBillboardOrder
+{
+ DWORD _TemplateID; //模板ID
+ WORD OrderA; //名次A
+ WORD OrderB; //至名次B
+ DWORD CTGAtleast; //至少充值RMB
+ list AwardItemList; //奖励物品列表[[物品ID,个数,是否拍品], ...]
+};
+
//神秘商店表
struct tagMysteryShop
diff --git a/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini b/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
index 9fa7b62..f1fae7f 100644
--- a/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
+++ b/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
@@ -386,6 +386,17 @@
PacketSubCMD_2=0x03
PacketCallFunc_2=OnForceQuitCrossState
+[CrossBillboard]
+ScriptName = GameWorldLogic\CrossBillboard.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 1
+
+PacketCMD_1=0xC0
+PacketSubCMD_1=0x04
+PacketCallFunc_1=OnViewCrossBillboard
+
[PlayerXMZZ]
ScriptName = Player\PlayerXMZZ.py
Writer = xdh
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
index 734ef0f..1282455 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -3767,6 +3767,66 @@
#------------------------------------------------------
+# C0 04 查看跨服排行榜 #tagCGViewCrossBillboard
+
+class tagCGViewCrossBillboard(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("Type", c_ubyte), #榜单类型
+ ("GroupValue1", c_ubyte), # 分组值1
+ ("GroupValue2", c_ubyte), # 分组值2,与分组值1组合归为同组榜单数据
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC0
+ self.SubCmd = 0x04
+ return
+
+ def ReadData(self, stringData, _pos=0, _len=0):
+ self.Clear()
+ memmove(addressof(self), stringData[_pos:], self.GetLength())
+ return _pos + self.GetLength()
+
+ def Clear(self):
+ self.Cmd = 0xC0
+ self.SubCmd = 0x04
+ self.Type = 0
+ self.GroupValue1 = 0
+ self.GroupValue2 = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCGViewCrossBillboard)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 04 查看跨服排行榜 //tagCGViewCrossBillboard:
+ Cmd:%s,
+ SubCmd:%s,
+ Type:%d,
+ GroupValue1:%d,
+ GroupValue2:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.Type,
+ self.GroupValue1,
+ self.GroupValue2
+ )
+ return DumpString
+
+
+m_NAtagCGViewCrossBillboard=tagCGViewCrossBillboard()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGViewCrossBillboard.Cmd,m_NAtagCGViewCrossBillboard.SubCmd))] = m_NAtagCGViewCrossBillboard
+
+
+#------------------------------------------------------
# C0 01 查看跨服竞技场赛季排行榜 #tagCGViewCrossPKBillboard
class tagCGViewCrossPKBillboard(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index 054a382..f873f17 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -5067,6 +5067,70 @@
#------------------------------------------------------
+# AC 12 跨服运营活动结束 # tagGCCrossActEnd
+
+class tagGCCrossActEnd(Structure):
+ Head = tagHead()
+ ActNameLen = 0 #(BYTE ActNameLen)
+ ActName = "" #(String ActName)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xAC
+ self.Head.SubCmd = 0x12
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.ActNameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ActName,_pos = CommFunc.ReadString(_lpData, _pos,self.ActNameLen)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xAC
+ self.Head.SubCmd = 0x12
+ self.ActNameLen = 0
+ self.ActName = ""
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += len(self.ActName)
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.ActNameLen)
+ data = CommFunc.WriteString(data, self.ActNameLen, self.ActName)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ ActNameLen:%d,
+ ActName:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.ActNameLen,
+ self.ActName
+ )
+ return DumpString
+
+
+m_NAtagGCCrossActEnd=tagGCCrossActEnd()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCCrossActEnd.Head.Cmd,m_NAtagGCCrossActEnd.Head.SubCmd))] = m_NAtagGCCrossActEnd
+
+
+#------------------------------------------------------
# AC 09 仙界盛典活动信息 #tagGCFairyCeremonyInfo
class tagGCFairyCeremonyInfo(Structure):
@@ -11037,6 +11101,190 @@
m_NAtagGCTeamMemFuncDataList=tagGCTeamMemFuncDataList()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCTeamMemFuncDataList.Head.Cmd,m_NAtagGCTeamMemFuncDataList.Head.SubCmd))] = m_NAtagGCTeamMemFuncDataList
+
+
+#------------------------------------------------------
+# C0 07 跨服排行榜信息 #tagGCCrossBillboardInfo
+
+class tagGCCrossBillboardData(Structure):
+ ID = 0 #(DWORD ID)
+ Name1 = "" #(char Name1[33])//名字1,用来显示排序对象名字
+ Name2 = "" #(char Name2[33])//名字2
+ Type2 = 0 #(BYTE Type2)//附加类型,用来表示排序对象的类型,比如,玩家所属职业门派,宠物类型等
+ Value1 = 0 #(DWORD Value1)//自定义值1
+ Value2 = 0 #(DWORD Value2)//自定义值2
+ CmpValue = 0 #(DWORD CmpValue)// 比较权值
+ CmpValue2 = 0 #(DWORD CmpValue2)// 比较权值
+ CmpValue3 = 0 #(DWORD CmpValue3)// 比较权值
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.ID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name1,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.Name2,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.Type2,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.Value1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Value2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.CmpValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.CmpValue2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.CmpValue3,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.ID = 0
+ self.Name1 = ""
+ self.Name2 = ""
+ self.Type2 = 0
+ self.Value1 = 0
+ self.Value2 = 0
+ self.CmpValue = 0
+ self.CmpValue2 = 0
+ self.CmpValue3 = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 33
+ length += 1
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.ID)
+ data = CommFunc.WriteString(data, 33, self.Name1)
+ data = CommFunc.WriteString(data, 33, self.Name2)
+ data = CommFunc.WriteBYTE(data, self.Type2)
+ data = CommFunc.WriteDWORD(data, self.Value1)
+ data = CommFunc.WriteDWORD(data, self.Value2)
+ data = CommFunc.WriteDWORD(data, self.CmpValue)
+ data = CommFunc.WriteDWORD(data, self.CmpValue2)
+ data = CommFunc.WriteDWORD(data, self.CmpValue3)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ ID:%d,
+ Name1:%s,
+ Name2:%s,
+ Type2:%d,
+ Value1:%d,
+ Value2:%d,
+ CmpValue:%d,
+ CmpValue2:%d,
+ CmpValue3:%d
+ '''\
+ %(
+ self.ID,
+ self.Name1,
+ self.Name2,
+ self.Type2,
+ self.Value1,
+ self.Value2,
+ self.CmpValue,
+ self.CmpValue2,
+ self.CmpValue3
+ )
+ return DumpString
+
+
+class tagGCCrossBillboardInfo(Structure):
+ Head = tagHead()
+ Type = 0 #(BYTE Type)//榜单类型
+ GroupValue1 = 0 #(BYTE GroupValue1)// 分组值1
+ GroupValue2 = 0 #(BYTE GroupValue2)// 分组值2,与分组值1组合归为同组榜单数据
+ BillboardCount = 0 #(BYTE BillboardCount)
+ CrossBillboardDataList = list() #(vector<tagGCCrossBillboardData> CrossBillboardDataList)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x07
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.Type,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupValue1,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupValue2,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.BillboardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.BillboardCount):
+ temCrossBillboardDataList = tagGCCrossBillboardData()
+ _pos = temCrossBillboardDataList.ReadData(_lpData, _pos)
+ self.CrossBillboardDataList.append(temCrossBillboardDataList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x07
+ self.Type = 0
+ self.GroupValue1 = 0
+ self.GroupValue2 = 0
+ self.BillboardCount = 0
+ self.CrossBillboardDataList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += 1
+ length += 1
+ length += 1
+ for i in range(self.BillboardCount):
+ length += self.CrossBillboardDataList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.Type)
+ data = CommFunc.WriteBYTE(data, self.GroupValue1)
+ data = CommFunc.WriteBYTE(data, self.GroupValue2)
+ data = CommFunc.WriteBYTE(data, self.BillboardCount)
+ for i in range(self.BillboardCount):
+ data = CommFunc.WriteString(data, self.CrossBillboardDataList[i].GetLength(), self.CrossBillboardDataList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ Type:%d,
+ GroupValue1:%d,
+ GroupValue2:%d,
+ BillboardCount:%d,
+ CrossBillboardDataList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.Type,
+ self.GroupValue1,
+ self.GroupValue2,
+ self.BillboardCount,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCCrossBillboardInfo=tagGCCrossBillboardInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCCrossBillboardInfo.Head.Cmd,m_NAtagGCCrossBillboardInfo.Head.SubCmd))] = m_NAtagGCCrossBillboardInfo
#------------------------------------------------------
@@ -25809,6 +26057,427 @@
#------------------------------------------------------
+# AA 32 跨服充值排行活动信息 #tagMCCACTGBillboardInfo
+
+class tagMCCACTGBillboardAwardItem(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("ItemID", c_int),
+ ("ItemCount", c_ushort),
+ ("IsBind", c_ubyte), # 是否拍品
+ ]
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, stringData, _pos=0, _len=0):
+ self.Clear()
+ memmove(addressof(self), stringData[_pos:], self.GetLength())
+ return _pos + self.GetLength()
+
+ def Clear(self):
+ self.ItemID = 0
+ self.ItemCount = 0
+ self.IsBind = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagMCCACTGBillboardAwardItem)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// AA 32 跨服充值排行活动信息 //tagMCCACTGBillboardInfo:
+ ItemID:%d,
+ ItemCount:%d,
+ IsBind:%d
+ '''\
+ %(
+ self.ItemID,
+ self.ItemCount,
+ self.IsBind
+ )
+ return DumpString
+
+
+class tagMCCACTGBillboardDabiao(Structure):
+ AwardIndex = 0 #(BYTE AwardIndex)// 奖励索引 0~31
+ NeedRMB = 0 #(DWORD NeedRMB)// 所需充值RMB
+ AwardItemCount = 0 #(BYTE AwardItemCount)// 奖励物品数
+ AwardItemList = list() #(vector<tagMCCACTGBillboardAwardItem> AwardItemList)// 奖励物品信息
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.AwardIndex,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.NeedRMB,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.AwardItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.AwardItemCount):
+ temAwardItemList = tagMCCACTGBillboardAwardItem()
+ _pos = temAwardItemList.ReadData(_lpData, _pos)
+ self.AwardItemList.append(temAwardItemList)
+ return _pos
+
+ def Clear(self):
+ self.AwardIndex = 0
+ self.NeedRMB = 0
+ self.AwardItemCount = 0
+ self.AwardItemList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 4
+ length += 1
+ for i in range(self.AwardItemCount):
+ length += self.AwardItemList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.AwardIndex)
+ data = CommFunc.WriteDWORD(data, self.NeedRMB)
+ data = CommFunc.WriteBYTE(data, self.AwardItemCount)
+ for i in range(self.AwardItemCount):
+ data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ AwardIndex:%d,
+ NeedRMB:%d,
+ AwardItemCount:%d,
+ AwardItemList:%s
+ '''\
+ %(
+ self.AwardIndex,
+ self.NeedRMB,
+ self.AwardItemCount,
+ "..."
+ )
+ return DumpString
+
+
+class tagMCCACTGBillboardOrder(Structure):
+ OrderA = 0 #(BYTE OrderA)// 名次A
+ OrderB = 0 #(BYTE OrderB)// 至名次B
+ NeedRMB = 0 #(DWORD NeedRMB)// 所需充值RMB,未达标的该名次空,排名后面的玩家向下顺延
+ AwardItemCount = 0 #(BYTE AwardItemCount)// 奖励物品数
+ AwardItemList = list() #(vector<tagMCCACTGBillboardAwardItem> AwardItemList)// 奖励物品信息
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.OrderA,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.OrderB,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.NeedRMB,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.AwardItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.AwardItemCount):
+ temAwardItemList = tagMCCACTGBillboardAwardItem()
+ _pos = temAwardItemList.ReadData(_lpData, _pos)
+ self.AwardItemList.append(temAwardItemList)
+ return _pos
+
+ def Clear(self):
+ self.OrderA = 0
+ self.OrderB = 0
+ self.NeedRMB = 0
+ self.AwardItemCount = 0
+ self.AwardItemList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 1
+ length += 4
+ length += 1
+ for i in range(self.AwardItemCount):
+ length += self.AwardItemList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.OrderA)
+ data = CommFunc.WriteBYTE(data, self.OrderB)
+ data = CommFunc.WriteDWORD(data, self.NeedRMB)
+ data = CommFunc.WriteBYTE(data, self.AwardItemCount)
+ for i in range(self.AwardItemCount):
+ data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ OrderA:%d,
+ OrderB:%d,
+ NeedRMB:%d,
+ AwardItemCount:%d,
+ AwardItemList:%s
+ '''\
+ %(
+ self.OrderA,
+ self.OrderB,
+ self.NeedRMB,
+ self.AwardItemCount,
+ "..."
+ )
+ return DumpString
+
+
+class tagMCCACTGBillboardTempInfo(Structure):
+ TemplateID = 0 #(BYTE TemplateID)// 活动模板ID
+ DabiaoAwardCount = 0 #(BYTE DabiaoAwardCount)// 达标奖励档数
+ DabiaoAwardInfo = list() #(vector<tagMCCACTGBillboardDabiao> DabiaoAwardInfo)// 达标奖励信息
+ OrderAwardCount = 0 #(BYTE OrderAwardCount)// 排行奖励档数
+ OrderAwardInfo = list() #(vector<tagMCCACTGBillboardOrder> OrderAwardInfo)// 排行奖励信息
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.TemplateID,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.DabiaoAwardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.DabiaoAwardCount):
+ temDabiaoAwardInfo = tagMCCACTGBillboardDabiao()
+ _pos = temDabiaoAwardInfo.ReadData(_lpData, _pos)
+ self.DabiaoAwardInfo.append(temDabiaoAwardInfo)
+ self.OrderAwardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.OrderAwardCount):
+ temOrderAwardInfo = tagMCCACTGBillboardOrder()
+ _pos = temOrderAwardInfo.ReadData(_lpData, _pos)
+ self.OrderAwardInfo.append(temOrderAwardInfo)
+ return _pos
+
+ def Clear(self):
+ self.TemplateID = 0
+ self.DabiaoAwardCount = 0
+ self.DabiaoAwardInfo = list()
+ self.OrderAwardCount = 0
+ self.OrderAwardInfo = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 1
+ for i in range(self.DabiaoAwardCount):
+ length += self.DabiaoAwardInfo[i].GetLength()
+ length += 1
+ for i in range(self.OrderAwardCount):
+ length += self.OrderAwardInfo[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.TemplateID)
+ data = CommFunc.WriteBYTE(data, self.DabiaoAwardCount)
+ for i in range(self.DabiaoAwardCount):
+ data = CommFunc.WriteString(data, self.DabiaoAwardInfo[i].GetLength(), self.DabiaoAwardInfo[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.OrderAwardCount)
+ for i in range(self.OrderAwardCount):
+ data = CommFunc.WriteString(data, self.OrderAwardInfo[i].GetLength(), self.OrderAwardInfo[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ TemplateID:%d,
+ DabiaoAwardCount:%d,
+ DabiaoAwardInfo:%s,
+ OrderAwardCount:%d,
+ OrderAwardInfo:%s
+ '''\
+ %(
+ self.TemplateID,
+ self.DabiaoAwardCount,
+ "...",
+ self.OrderAwardCount,
+ "..."
+ )
+ return DumpString
+
+
+class tagMCCACTGBillboardInfo(Structure):
+ Head = tagHead()
+ ServerInfoLen = 0 #(BYTE ServerInfoLen)
+ ServerIDRangeInfo = "" #(String ServerIDRangeInfo)//开放该活动的服务器ID范围列表,json格式 [[IDA, IDB], ...], [] 为全服
+ GroupValue1 = 0 #(BYTE GroupValue1)// 活动榜单分组值1,用于查询对应榜单
+ StartDate = "" #(char StartDate[10])// 开始日期 y-m-d
+ EndtDate = "" #(char EndtDate[10])// 结束日期 y-m-d
+ TemplateID = 0 #(BYTE TemplateID)// 当前活动模板ID
+ TemplateCount = 0 #(BYTE TemplateCount)
+ TempInfo = list() #(vector<tagMCCACTGBillboardTempInfo> TempInfo)// 模板信息
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xAA
+ self.Head.SubCmd = 0x32
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.ServerInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ServerIDRangeInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.ServerInfoLen)
+ self.GroupValue1,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+ self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+ self.TemplateID,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.TemplateCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.TemplateCount):
+ temTempInfo = tagMCCACTGBillboardTempInfo()
+ _pos = temTempInfo.ReadData(_lpData, _pos)
+ self.TempInfo.append(temTempInfo)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xAA
+ self.Head.SubCmd = 0x32
+ self.ServerInfoLen = 0
+ self.ServerIDRangeInfo = ""
+ self.GroupValue1 = 0
+ self.StartDate = ""
+ self.EndtDate = ""
+ self.TemplateID = 0
+ self.TemplateCount = 0
+ self.TempInfo = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += len(self.ServerIDRangeInfo)
+ length += 1
+ length += 10
+ length += 10
+ length += 1
+ length += 1
+ for i in range(self.TemplateCount):
+ length += self.TempInfo[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.ServerInfoLen)
+ data = CommFunc.WriteString(data, self.ServerInfoLen, self.ServerIDRangeInfo)
+ data = CommFunc.WriteBYTE(data, self.GroupValue1)
+ data = CommFunc.WriteString(data, 10, self.StartDate)
+ data = CommFunc.WriteString(data, 10, self.EndtDate)
+ data = CommFunc.WriteBYTE(data, self.TemplateID)
+ data = CommFunc.WriteBYTE(data, self.TemplateCount)
+ for i in range(self.TemplateCount):
+ data = CommFunc.WriteString(data, self.TempInfo[i].GetLength(), self.TempInfo[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ ServerInfoLen:%d,
+ ServerIDRangeInfo:%s,
+ GroupValue1:%d,
+ StartDate:%s,
+ EndtDate:%s,
+ TemplateID:%d,
+ TemplateCount:%d,
+ TempInfo:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.ServerInfoLen,
+ self.ServerIDRangeInfo,
+ self.GroupValue1,
+ self.StartDate,
+ self.EndtDate,
+ self.TemplateID,
+ self.TemplateCount,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagMCCACTGBillboardInfo=tagMCCACTGBillboardInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCCACTGBillboardInfo.Head.Cmd,m_NAtagMCCACTGBillboardInfo.Head.SubCmd))] = m_NAtagMCCACTGBillboardInfo
+
+
+#------------------------------------------------------
+# AA 33 跨服充值排行活动玩家信息 #tagMCCACTGBillboardPlayerInfo
+
+class tagMCCACTGBillboardPlayerInfo(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("CTGRMBTotal", c_int), # 活动已累计充值RMB
+ ("DabiaoAwardRecord", c_int), # 达标奖励记录,与达标奖励索引位或运算判断是否已领取
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xAA
+ self.SubCmd = 0x33
+ return
+
+ def ReadData(self, stringData, _pos=0, _len=0):
+ self.Clear()
+ memmove(addressof(self), stringData[_pos:], self.GetLength())
+ return _pos + self.GetLength()
+
+ def Clear(self):
+ self.Cmd = 0xAA
+ self.SubCmd = 0x33
+ self.CTGRMBTotal = 0
+ self.DabiaoAwardRecord = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagMCCACTGBillboardPlayerInfo)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// AA 33 跨服充值排行活动玩家信息 //tagMCCACTGBillboardPlayerInfo:
+ Cmd:%s,
+ SubCmd:%s,
+ CTGRMBTotal:%d,
+ DabiaoAwardRecord:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.CTGRMBTotal,
+ self.DabiaoAwardRecord
+ )
+ return DumpString
+
+
+m_NAtagMCCACTGBillboardPlayerInfo=tagMCCACTGBillboardPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCCACTGBillboardPlayerInfo.Cmd,m_NAtagMCCACTGBillboardPlayerInfo.SubCmd))] = m_NAtagMCCACTGBillboardPlayerInfo
+
+
+#------------------------------------------------------
# AA 09 消费返利活动信息 #tagMCCostRebateInfo
class tagMCCostRebateAwardItem(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardDataCross.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardDataCross.py
new file mode 100644
index 0000000..c8d0327
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardDataCross.py
@@ -0,0 +1,107 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.BillboardDataCross
+#
+# @todo:跨服榜单数据
+# @author hxp
+# @date 2021-01-13
+# @version 1.0
+#
+# 详细描述: 跨服榜单数据
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2021-01-13 17:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import PyDataManager
+import CrossBillboard
+
+def __Help(curPlayer, errInfo=""):
+ GameWorld.DebugAnswer(curPlayer, "---------- %s" % GameWorld.GetCurrentDataTimeStr())
+ if errInfo:
+ GameWorld.DebugAnswer(curPlayer, errInfo)
+ GameWorld.DebugAnswer(curPlayer, "新增跨服榜单假数据: BillboardDataCross 类型 分组值1 分组值2 条数 比较值1 可选参数(比较值2 常规值1 常规值2)")
+ GameWorld.DebugAnswer(curPlayer, "删除跨服榜单假数据: BillboardDataCross 类型 分组值1 分组值2")
+ GameWorld.DebugAnswer(curPlayer, "跨服运营活动榜类型:150-充值")
+ return
+
+## 执行逻辑
+# @param curPlayer 当前玩家
+# @param gmList []
+# @return None
+def OnExec(curPlayer, gmList):
+
+ paramLen = len(gmList)
+ if paramLen < 3:
+ __Help(curPlayer)
+ return
+
+ billboardType = gmList[0]
+ if billboardType not in ShareDefine.CrossBillboardTypeList:
+ __Help(curPlayer, "榜单类型不存在!")
+ return
+
+ GameWorld.DebugAnswer(curPlayer, "发送完毕,执行结果查看跨服服务器!")
+ return
+
+def OnGetMergeParam(curPlayer):
+ ## 跨服命令额外参数
+ return []
+
+def OnMergeServerExec(gmList, tick):
+ ## 跨服执行命令
+
+ paramLen = len(gmList)
+ if paramLen < 3:
+ return
+
+ billboardType = gmList[0]
+ groupValue1 = gmList[1]
+ groupValue2 = gmList[2]
+
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+
+ curDataCount = billboardObj.GetCount()
+ maxDataCount = billboardObj.GetMaxCount()
+
+ # 清除榜单假数据
+ if paramLen == 3:
+ billboardObj.ClearData()
+ GameWorld.Log("删除跨服榜单(%s-%s-%s): %s 条" % (billboardType, groupValue1, groupValue2, curDataCount))
+ return
+
+ count = gmList[3] if len(gmList) > 3 else 0
+ cmpValue1 = gmList[4] if len(gmList) > 4 else 0
+ cmpValue2 = gmList[5] if len(gmList) > 5 else 0
+ value1 = gmList[6] if len(gmList) > 6 else 0
+ value2 = gmList[7] if len(gmList) > 7 else 0
+
+ id2 = 0
+ type2 = 0
+ name2 = ""
+ cmpValue3 = 0
+
+ count = min(count, maxDataCount - curDataCount)
+ FakeName = "假名字".decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())
+
+ for i in xrange(count):
+ dataPlayerID = curDataCount + 1 + i
+ dataPlayerName = "%s%s" % (FakeName, i)
+ dataCmpValue1 = max(0, cmpValue1 - i)
+ dataCmpValue2 = max(0, cmpValue2 - i)
+
+ dataID = dataPlayerID
+ name1 = dataPlayerName
+ cmpValue = dataCmpValue1
+ cmpValue2 = dataCmpValue2
+ CrossBillboard.UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue, cmpValue2, cmpValue3, groupValue2, id2)
+
+ GameWorld.Log("插入虚假榜单(%s-%s-%s): %s 条" % (billboardType, groupValue1, groupValue2, count))
+ return
+
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_CrossActServerIDChange.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_CrossActServerIDChange.py
new file mode 100644
index 0000000..7cb503f
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_CrossActServerIDChange.py
@@ -0,0 +1,170 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.GMT_CrossActServerIDChange
+#
+# @todo:跨服活动区服ID修改
+# @author hxp
+# @date 2021-01-13
+# @version 1.0
+#
+# 详细描述: 跨服活动区服ID修改
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2021-01-13 17:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import DataRecordPack
+import CrossActionControl
+import CrossRealmMsg
+import ShareDefine
+import GMCommon
+
+#---------------------------------------------------------------------
+
+## 执行逻辑
+# @param curPlayer 当前玩家
+# @param gmCmdDict: 命令字典
+# @return None
+# @remarks 函数详细说明.
+def OnExec(orderId, gmCmdDict):
+
+ GameWorld.Log("GMT_CrossActServerIDChange gmCmdDict=%s" % str(gmCmdDict))
+
+ if not GameWorld.IsCrossServer():
+ GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_IsNotCrossServer)
+ return
+
+ errInfo = ""
+ doChange = gmCmdDict.get("doChange")
+ if doChange:
+ errInfo = __DoChangeCrossActServerIDRangeList(gmCmdDict)
+
+ crossActInfoDict = CrossActionControl.GetCrossActInfoDict()
+ backMsg = {"crossActInfoDict":crossActInfoDict}
+ if errInfo:
+ backMsg["ErrorInfo"] = errInfo
+ GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_ParamErr, backMsg)
+ return
+
+ # 记录流向
+ DataRecordPack.DR_ToolGMOperate(0, '', '', 'GMT_CrossActServerIDChange', str(gmCmdDict))
+ # 回复
+ GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_Success, backMsg)
+ return
+
+def __DoChangeCrossActServerIDRangeList(gmCmdDict):
+
+ crossActInfoDict = CrossActionControl.GetCrossActInfoDict()
+ changeInfoDict = {} # {actName:{cfgID:ServerIDList, ...}, ...}
+ for k, v in gmCmdDict.items():
+ if not k.endswith("_ServerIDRangeList"):
+ continue
+ kspList = k.split("_")
+ if len(kspList) != 3:
+ continue
+ actName, cfgID, _ = kspList
+ try:
+ cfgID = int(cfgID)
+ changeServerIDList = eval(v)
+ # 检查修改格式是否正确
+ for changeList in changeServerIDList:
+ if not (isinstance(changeList, list)
+ and len(changeList) == 2
+ and isinstance(changeList[0], int)
+ and isinstance(changeList[1], int)
+ ):
+ errInfo = "%s CfgID(%s) error serverIDList(%s)" % (actName, cfgID, changeList)
+ return errInfo
+ except:
+ errInfo = "%s CfgID(%s) error %s" % (actName, cfgID, v)
+ return errInfo
+
+ if actName not in changeInfoDict:
+ changeInfoDict[actName] = {}
+ changeInfoDict[actName][cfgID] = changeServerIDList
+
+ GameWorld.Log(" crossActInfoDict=%s" % crossActInfoDict)
+ GameWorld.Log(" changeInfoDict=%s" % changeInfoDict)
+ if not changeInfoDict:
+ errInfo = "no change info!"
+ return errInfo
+
+ # 检查修改后是否有交叉
+ checkGroupInfo = {} # {actName:{actGroupName:[cfgID, ...], ...}} # 先分组
+ for actName, actInfoDict in crossActInfoDict.items():
+ if actName not in changeInfoDict:
+ # 没有修改的活动不需要检查
+ continue
+ if actName not in checkGroupInfo:
+ checkGroupInfo[actName] = {}
+ actGroupListDict = checkGroupInfo[actName]
+ for cfgID, actInfo in actInfoDict.items():
+ actGroupName = actInfo[ShareDefine.ActKey_IpyDataInfo]["ActGroupName"]
+ if actGroupName not in actGroupListDict:
+ actGroupListDict[actGroupName] = []
+ cfgIDList = actGroupListDict[actGroupName]
+ cfgIDList.append(cfgID)
+
+ GameWorld.Log(" checkGroupInfo: %s" % checkGroupInfo)
+
+ for actName, actGroupListDict in checkGroupInfo.items():
+ actInfoDict = crossActInfoDict[actName]
+ changeInfo = changeInfoDict.get(actName, {})
+ for actGroupName, cfgIDList in actGroupListDict.items():
+ allServerIDRangeList = []
+ for cfgID in cfgIDList:
+ befActInfo = actInfoDict[cfgID]
+ if cfgID in changeInfo:
+ allServerIDRangeList.extend(changeInfo[cfgID])
+ else:
+ befServerIDList = befActInfo[ShareDefine.ActKey_ServerIDRangeList]
+ allServerIDRangeList.extend(befServerIDList)
+
+ GameWorld.Log(" actName=%s,actGroupName=%s,cfgIDList=%s" % (actName, actGroupName, cfgIDList))
+ GameWorld.Log(" allServerIDRangeList=%s" % (allServerIDRangeList))
+ errorServerIDList = []
+ for i in xrange(len(allServerIDRangeList)):
+ checkIDA, checkIDB = allServerIDRangeList[i]
+ for j in xrange(i):
+ serverIDA, serverIDB = allServerIDRangeList[j]
+ if serverIDA <= checkIDA <= serverIDB:
+ errorServerIDList.append(checkIDA)
+
+ if serverIDA <= checkIDB <= serverIDB:
+ errorServerIDList.append(checkIDB)
+
+ GameWorld.Log(" errorServerIDList=%s" % (errorServerIDList))
+ if errorServerIDList:
+ return "%s exist errorServerIDList=%s in actGroupName(%s)" % (actName, errorServerIDList, actGroupName)
+
+ # 检查通过后进行修改
+ sysnCrossActInfoDict = {}
+ GameWorld.Log(" do change...")
+ for actName, changInfo in changeInfoDict.items():
+ for cfgID, changeServerIDRangeList in changInfo.items():
+ if actName not in crossActInfoDict:
+ continue
+ if cfgID not in crossActInfoDict[actName]:
+ continue
+ actInfoDict = crossActInfoDict[actName][cfgID]
+ beforeServerIDRangeList = actInfoDict[ShareDefine.ActKey_ServerIDRangeList]
+ # 直接覆盖替换
+ actInfoDict[ShareDefine.ActKey_ServerIDRangeList] = changeServerIDRangeList
+
+ GameWorld.Log(" actName=%s,cfgID=%s,beforeServerIDRangeList=%s -> %s"
+ % (actName, cfgID, beforeServerIDRangeList, changeServerIDRangeList))
+
+ if actName not in sysnCrossActInfoDict:
+ sysnCrossActInfoDict[actName] = {}
+ sysnCrossActInfoDict[actName][cfgID] = actInfoDict
+
+ GameWorld.Log(" changeOK! crossActInfoDict=%s" % crossActInfoDict)
+
+ # 同步子服务器
+ serverGroupIDList = []
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossActInfo, sysnCrossActInfoDict, serverGroupIDList)
+ return ""
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_QueryBillboardCross.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_QueryBillboardCross.py
new file mode 100644
index 0000000..16a067f
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_QueryBillboardCross.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.GMT_QueryBillboardCross
+#
+# @todo:查询跨服排行榜
+# @author hxp
+# @date 2021-01-13
+# @version 1.0
+#
+# 详细描述: 查询跨服排行榜
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2021-01-13 17:00"""
+#-------------------------------------------------------------------------------
+
+#导入
+import GMCommon
+import ShareDefine
+import PyDataManager
+import GameWorld
+
+
+#逻辑实现(这里curPlayer = None)
+## 执行逻辑
+# @param curPlayer 当前玩家
+# @param gmList [cmdIndex gmAccID forbidAcc]
+# @return None
+# @remarks 函数详细说明.
+def OnExec(orderId, gmCmdDict):
+
+ if not GameWorld.IsCrossServer():
+ GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_IsNotCrossServer)
+ return
+
+ billboardType = GameWorld.ToIntDef(gmCmdDict.get('billboardType', ''), None)
+ billType = GameWorld.ToIntDef(gmCmdDict.get('billType', ''), None) # 其他指定类型
+ if billType != None:
+ billboardType = billType
+
+ if billboardType == None or billboardType not in ShareDefine.CrossBillboardTypeList:
+ GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_TypeNumErr)
+ return
+
+ groupValue1 = GameWorld.ToIntDef(gmCmdDict.get('groupValue1', ''), None)
+ groupValue2 = GameWorld.ToIntDef(gmCmdDict.get('groupValue2', ''), None)
+
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ groupList = billboardMgr.GetBillboardGroupList(billboardType)
+
+ backMsg = {"billboardType":billboardType, "groupList":groupList}
+
+ if groupValue1 != None and groupValue2 != None:
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+
+ billboardInfo = []
+ for i in xrange(billboardObj.GetCount()):
+ billboardData = billboardObj.At(i)
+ if not billboardData:
+ continue
+ billboardDict = {
+ "ID":billboardData.ID,
+ "ID2":billboardData.ID2,
+ "Name1":billboardData.Name1,
+ "Name2":billboardData.Name2,
+ "Type2":billboardData.Type2,
+ "Value1":billboardData.Value1,
+ "Value2":billboardData.Value2,
+ "CmpValue":billboardData.CmpValue,
+ "CmpValue2":billboardData.CmpValue2,
+ "CmpValue3":billboardData.CmpValue3,
+ }
+
+ for k, v in billboardDict.items():
+ if not v:
+ billboardDict.pop(k)
+
+ billboardInfo.append(billboardDict)
+
+ backMsg.update({"billboardInfo":billboardInfo, "groupValue1":groupValue1, "groupValue2":groupValue2})
+
+ #执行成功
+ GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_Success, backMsg)
+ return
+
+
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/GMShell.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/GMShell.py
index 6f97c43..7a34771 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GM/GMShell.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/GMShell.py
@@ -87,13 +87,22 @@
GameWorld.Log("###使用GM命令 = %s错误,玩家不是GM"%(callFunName), curPlayer.GetPlayerID())
return
+ #把剩余参数转换为整型
+ for i in range(0, len(alist)):
+ if i == 0:
+ continue
+ value = GameWorld.ToIntDef(alist[i], None)
+ if value == None:
+ #GameWorld.DebugAnswer(curPlayer, "参数错误, 参数%s必须为纯数字!" % (i + 1))
+ continue
+ alist[i] = value
+
#非跨服服务器下使用跨服GM命令,则发送到跨服
if not GameWorld.IsCrossServer():
callFunc = GameWorld.GetExecFunc(Commands, "%s.%s"%(callFunName, "OnGetMergeParam"))
if callFunc != None:
extendParamList = callFunc(curPlayer)
- alist.extend(extendParamList)
- CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_GMCMD, alist)
+ CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_GMCMD, alist + extendParamList)
callFunc = GameWorld.GetExecFunc(Commands, "%s.%s"%(callFunName, "OnExec"))
if callFunc == None:
@@ -102,17 +111,7 @@
GameWorld.DebugAnswer(curPlayer, 'no cmd !!!')
return
- #删除命令,只将参数传入
- del alist[0]
- #把剩余参数转换为整型
- for i in range(0, len(alist)):
- value = GameWorld.ToIntDef(alist[i], None)
- if value == None:
- #GameWorld.DebugAnswer(curPlayer, "参数错误, 参数%s必须为纯数字!" % (i + 1))
- continue
- alist[i] = value
-
- callFunc(curPlayer,alist)
+ callFunc(curPlayer, alist[1:])
except BaseException:
GameWorld.DebugAnswer(curPlayer, "执行GM命令错误, 请查看GameServer日志!")
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActCTGBillboard.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActCTGBillboard.py
new file mode 100644
index 0000000..b7970fa
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActCTGBillboard.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package CrossActCTGBillboard
+#
+# @todo:跨服运营活动 - 充值排行
+# @author hxp
+# @date 2021-01-13
+# @version 1.0
+#
+# 详细描述: 跨服运营活动 - 充值排行
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2021-01-13 17:00"""
+#-------------------------------------------------------------------------------
+
+import ShareDefine
+import PyDataManager
+import PlayerCompensation
+import IpyGameDataPY
+import GameWorld
+
+def OnActIDChange(cfgID, dbTemplateID, state):
+ ## 活动ID变更
+
+ # 先结算上期活动
+ __GiveBillboardOrderAward(cfgID, dbTemplateID)
+
+ # 如果有新活动,处理新活动
+ if not state:
+ return
+
+ groupValue1 = cfgID
+ billboardType = ShareDefine.Def_CBT_ActCTG
+
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1)
+ billboardObj.ClearData() # 新活动重置榜单数据
+
+ return
+
+def __GiveBillboardOrderAward(cfgID, dbTemplateID):
+ ## 结算榜单排名奖励
+
+ groupValue1 = cfgID
+ billboardType = ShareDefine.Def_CBT_ActCTG
+
+ # 先结算上期活动
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1)
+ billboardDataCount = billboardObj.GetCount()
+ if not billboardDataCount:
+ GameWorld.Log("跨服充值排行数据为空! billboardType=%s,cfgID=%s" % (billboardType, cfgID))
+ return
+
+ # 结算时排序并保存榜单数据流向
+ billboardObj.SortData()
+ billboardObj.SaveDRData()
+
+ GameWorld.Log("结算跨服充值排行奖励: billboardType=%s,cfgID=%s,dbTemplateID=%s,billboardDataCount=%s"
+ % (billboardType, cfgID, dbTemplateID, billboardDataCount))
+
+ orderIpyDataList = IpyGameDataPY.GetIpyGameDataList("CrossActCTGBillboardOrder", dbTemplateID)
+ if not orderIpyDataList:
+ return
+
+ billboardIndex = 0
+ for ipyData in orderIpyDataList:
+ orderA = ipyData.GetOrderA()
+ orderB = ipyData.GetOrderB()
+ ctgAtleast = ipyData.GetCTGAtleast()
+ awardItemList = ipyData.GetAwardItemList()
+ orderCountTotal = orderB - orderA + 1 # 奖励名次数量
+ orderCount = 0
+
+ for index in xrange(billboardIndex, billboardDataCount):
+ if orderCount >= orderCountTotal:
+ break
+
+ billboardData = billboardObj.At(index)
+ playerID = billboardData.ID
+ ctgRMB = billboardData.CmpValue
+ if ctgRMB < ctgAtleast:
+ break
+
+ realOrder = orderA + orderCount
+ paramList = [realOrder]
+ PlayerCompensation.SendMailByKey("CABillboardCTGOrder", [playerID], awardItemList, paramList, crossMail=True)
+ GameWorld.Log(" playerID=%s,榜单名次=%s,实际名次=%s,充值总RMB=%s" % (playerID, index + 1, realOrder, ctgRMB))
+
+ orderCount += 1
+ billboardIndex += 1
+
+ # 结算完清除榜单数据
+ billboardObj.ClearData()
+ return
+
+
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
new file mode 100644
index 0000000..15bcc39
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
@@ -0,0 +1,523 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package CrossActionControl
+#
+# @todo:跨服活动总开关逻辑
+# @author hxp
+# @date 2020-01-13
+# @version 1.0
+#
+# 详细描述: 跨服活动总开关逻辑
+# 跨服活动的时间以跨服服务器为准,所有的状态控制由跨服服务器控制并广播子服务器
+# 子服仅做具体活动逻辑
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2020-01-13 17:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import PlayerControl
+import IpyGameDataPY
+import CrossActCTGBillboard
+import CrossRealmMsg
+import PyGameData
+import ChConfig
+
+import datetime
+import time
+
+(
+CrossAct_ReloadSign, # 信息重载标记
+CrossAct_TodayInfo, # 当日的活动信息
+) = range(2)
+
+def OnPlayerLogin(curPlayer):
+ return
+
+def OnServerClose():
+ if not GameWorld.IsCrossServer():
+ return
+
+ GameWorld.GetUniversalRecMgr().Delete(ShareDefine.Def_UniversalGameRecType_CrossActInfo)
+
+ if not PyGameData.g_crossActInfoDict:
+ return
+ GameWorld.Log("保存跨服运营活动信息通用记录: ")
+
+ # 保存活动中的
+ recDataList = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossActInfo)
+ for actName, actInfoDict in PyGameData.g_crossActInfoDict.items():
+ for cfgID, actInfo in actInfoDict.items():
+ if not actInfo.get(ShareDefine.ActKey_State):
+ # 非活动中的,已经结算过了,不需要存储
+ continue
+ state = actInfo.get(ShareDefine.ActKey_State, 0)
+ actID = actInfo.get(ShareDefine.ActKey_ID, 0)
+ templateID = actInfo.get(ShareDefine.ActKey_TemplateID, 0)
+ serverIDRangeList = actInfo.get(ShareDefine.ActKey_ServerIDRangeList, "")
+ recData = recDataList.AddRec()
+ recData.SetStrValue1(actName)
+ recData.SetStrValue3(str(serverIDRangeList))
+ recData.SetValue1(cfgID)
+ recData.SetValue2(state)
+ recData.SetValue3(actID)
+ recData.SetValue4(templateID)
+ GameWorld.Log(" actName=%s,cfgID=%s,state=%s,actID=%s,templateID=%s,serverIDRangeList=%s"
+ % (actName, cfgID, state, actID, templateID, serverIDRangeList))
+
+ return
+
+def GetCrossActInfoDict():
+ if PyGameData.g_crossActInfoDict == None:
+ PyGameData.g_crossActInfoDict = {}
+
+ # 先加载通用记录存储中的活动信息
+ recDataList = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossActInfo)
+ GameWorld.Log("加载通用记录中的跨服运营活动信息: %s" % recDataList.Count())
+ for index in xrange(recDataList.Count()):
+ recData = recDataList.At(index)
+ actName = recData.GetStrValue1()
+ strValue3 = recData.GetStrValue3()
+ serverIDRangeList = eval(strValue3) if strValue3 else []
+ cfgID = recData.GetValue1()
+ state = recData.GetValue2()
+ actID = recData.GetValue3()
+ templateID = recData.GetValue4()
+ if not state:
+ continue
+ if actName not in PyGameData.g_crossActInfoDict:
+ PyGameData.g_crossActInfoDict[actName] = {}
+ actInfoDict = PyGameData.g_crossActInfoDict[actName]
+ dbInfo = {ShareDefine.ActKey_ID:actID, ShareDefine.ActKey_State:state, ShareDefine.ActKey_TemplateID:templateID} # 活动ID、状态、模板信息单独存储,重置活动判断用
+ actInfo = {ShareDefine.ActKey_CfgID:cfgID, ShareDefine.ActKey_ServerIDRangeList:serverIDRangeList}
+ actInfo.update(dbInfo)
+ actInfo[ShareDefine.ActKey_DBInfo] = dbInfo
+ actInfoDict[cfgID] = actInfo
+
+ GameWorld.Log(" actName=%s,cfgID=%s, %s" % (actName, cfgID, actInfoDict))
+
+ return PyGameData.g_crossActInfoDict
+
+def __GetParseIpyDataList(ipyDataMgr, actName, actInfoDict):
+ ## 获取需要处理的合法分组活动配置列表,已经在活动中的必须要处理
+
+ groupInfo = {}
+ actCfgCount = getattr(ipyDataMgr, "Get%sCount" % actName)()
+ for cfgIndex in xrange(actCfgCount):
+ ipyData = getattr(ipyDataMgr, "Get%sByIndex" % actName)(cfgIndex)
+ actGroupName = ipyData.GetActGroupName()
+ if actGroupName not in groupInfo:
+ groupInfo[actGroupName] = []
+ groupIpyDataList = groupInfo[actGroupName]
+ groupIpyDataList.append(ipyData)
+
+ parseIpyDataList = []
+ for actGroupName, groupIpyDataList in groupInfo.items():
+ allOpen = False
+ cfgIDList = []
+ allServerIDRangeList = []
+ for ipyData in groupIpyDataList:
+ cfgID = ipyData.GetCfgID()
+ cfgIDList.append(cfgID)
+ serverIDRangeList = ipyData.GetServerIDRangeList()
+
+ if cfgID in actInfoDict and actInfoDict[cfgID]:
+ actInfo = actInfoDict[cfgID]
+ # 已经在活动中的记录必须要处理
+ parseIpyDataList.append(ipyData)
+ serverIDRangeList = actInfo[ShareDefine.ActKey_ServerIDRangeList]
+ GameWorld.Log(" 使用已经在活动中的记录的区服分组: cfgID=%s,serverIDRangeList=%s"
+ % (cfgID, serverIDRangeList))
+
+ # 没配置的全服开放
+ if not serverIDRangeList:
+ allOpen = True
+ else:
+ allServerIDRangeList.extend(serverIDRangeList)
+
+ if allOpen and len(groupIpyDataList) > 1:
+ GameWorld.ErrLog(" 同组活动服务器ID配置异常,有全服开放的,只能配置1条,不处理! actGroupName=%s,cfgIDList=%s" % (actGroupName, cfgIDList))
+ continue
+
+ errorServerIDList = []
+ for i in xrange(len(allServerIDRangeList)):
+ checkIDA, checkIDB = allServerIDRangeList[i]
+ for j in xrange(i):
+ serverIDA, serverIDB = allServerIDRangeList[j]
+ if serverIDA <= checkIDA <= serverIDB:
+ errorServerIDList.append(checkIDA)
+
+ if serverIDA <= checkIDB <= serverIDB:
+ errorServerIDList.append(checkIDB)
+
+ if errorServerIDList:
+ GameWorld.ErrLog(" 同组活动服务器ID配置异常,有交叉,不处理! actGroupName=%s,cfgIDList=%s,errorServerIDList=%s"
+ % (actGroupName, cfgIDList, errorServerIDList))
+ continue
+
+ for ipyData in groupIpyDataList:
+ cfgID = ipyData.GetCfgID()
+ if cfgID in actInfoDict and actInfoDict[cfgID]:
+ continue
+ parseIpyDataList.append(ipyData)
+
+ return parseIpyDataList
+
+def __GetCrossActInfo(isRefreshState=True):
+ # @return: isReload, CrossActInfo
+
+ key = "CrossActInfo"
+ CrossActInfo = IpyGameDataPY.GetConfigEx(key)
+ serverTime = GameWorld.GetServerTime()
+ curDateStr = "%d-%d-%d" % (serverTime.year, serverTime.month, serverTime.day)
+ curHour = serverTime.hour
+ reloadSignHour = 0 if curHour < 5 else 5
+ reloadSign = "%s %s" % (curDateStr, reloadSignHour)
+ if CrossActInfo and CrossActInfo[CrossAct_ReloadSign] == reloadSign:
+ #GameWorld.DebugLog("已经加载过本日跨服运营活动处理信息!reloadSign=%s" % reloadSign)
+ return False, CrossActInfo
+
+ # 因为后面的时间判断都是精确到分的,而处理此逻辑的时候可能不是0秒,所以这里的datetime取当前时间精确到分的
+ curDateTimeStr = "%s %02d:%02d:00" % (curDateStr, serverTime.hour, serverTime.minute)
+ curDateTime = datetime.datetime.strptime(curDateTimeStr, ChConfig.TYPE_Time_Format)
+
+ actTimeInfoDict = {}
+ ipyDataMgr = IpyGameDataPY.IPY_Data()
+
+ GameWorld.Log("=============================================================")
+ GameWorld.Log("加载本日跨服运营活动信息: %s, reloadSign=%s =====" % (curDateTime, reloadSign))
+ crossActInfoDict = GetCrossActInfoDict()
+ GameWorld.Log(" crossActInfoDict=%s" % crossActInfoDict)
+
+ for actName in ShareDefine.CrossActNameList:
+
+ # 取出本活动所属本服ID的所有配置
+ GameWorld.Log("加载跨服运营活动: actName=%s" % (actName))
+
+ if not hasattr(ipyDataMgr, "Get%sCount" % actName):
+ GameWorld.ErrLog(" 没有该跨服运营活动类型对应活动时间表! actName=%s" % actName)
+ continue
+
+ curActInfoDict = crossActInfoDict.get(actName, {})
+
+ # 验证服务器ID不重复的配置
+ parseIpyDataList = __GetParseIpyDataList(ipyDataMgr, actName, curActInfoDict)
+ for ipyData in parseIpyDataList:
+ cfgID = ipyData.GetCfgID()
+ startDateStr = ipyData.GetStartDate()
+ endDateStr = ipyData.GetEndDate()
+ GameWorld.Log(" cfgID=%s,startDateStr=%s,endDateStr=%s,curDateTime=%s" % (cfgID, startDateStr, endDateStr, curDateTime))
+ if not startDateStr:
+ startDateStr = curDateStr
+ GameWorld.Log(" 开始日期为空,默认每天,今日为: startDateStr=%s" % startDateStr)
+ if not endDateStr:
+ endDateStr = curDateStr
+ GameWorld.Log(" 结束日期为空,默认每天,今日为: endDateStr=%s" % endDateStr)
+
+ if hasattr(ipyData, "GetStartTimeList") and hasattr(ipyData, "GetEndTimeList"):
+ startHMStrList = ipyData.GetStartTimeList()
+ endHMStrList = ipyData.GetEndTimeList()
+ else:
+ startHMStrList = []
+ endHMStrList = []
+
+ notifyInfoDictStart = ipyData.GetNotifyInfoStart() if hasattr(ipyData, "GetNotifyInfoStart") else {}
+ notifyInfoDictEnd = ipyData.GetNotifyInfoEnd() if hasattr(ipyData, "GetNotifyInfoEnd") else {}
+ notifyInfoLoopInfo = ipyData.GetNotifyInfoLoop() if hasattr(ipyData, "GetNotifyInfoLoop") else [] # [循环分钟, 广播key, [广播参数列表可选]]
+
+ if len(startHMStrList) != len(endHMStrList):
+ GameWorld.ErrLog(" 活动配置开始及结束时间个数不匹配! actName=%s,cfgID=%s,startHMStrList=%s,endHMStrList=%s"
+ % (actName, cfgID, startHMStrList, endHMStrList))
+
+ resetType = 0 if not hasattr(ipyData, "GetResetType") else ipyData.GetResetType() # 重置类型,0-0点重置;1-5点重置
+ if resetType == 1:
+ startDayDate = datetime.datetime.strptime("%s 05:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)
+ endDayDate = datetime.datetime.strptime("%s 05:00:00" % (endDateStr), ChConfig.TYPE_Time_Format) # 结束日期5点
+ elif resetType == 2:
+ startDayDate = datetime.datetime.strptime("%s 05:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)
+ endDayDate = datetime.datetime.strptime("%s 00:00:00" % (endDateStr), ChConfig.TYPE_Time_Format) + datetime.timedelta(days=1) # 结束日期隔天0点
+ else:
+ startDayDate = datetime.datetime.strptime("%s 00:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)
+ endDayDate = datetime.datetime.strptime("%s 00:00:00" % (endDateStr), ChConfig.TYPE_Time_Format) + datetime.timedelta(days=1) # 结束日期隔天0点
+
+ GameWorld.Log(" resetType=%s,startDayDate=%s,endDayDate=%s,startHMStrList=%s,endHMStrList=%s"
+ % (resetType, startDayDate, endDayDate, startHMStrList, endHMStrList))
+
+ if curDateTime < startDayDate or curDateTime >= endDayDate:
+ isActTime = False
+ if cfgID not in curActInfoDict or not curActInfoDict[cfgID]:
+ GameWorld.Log(" 非活动时间!不处理!")
+ continue
+ else:
+ isActTime = True
+
+ GameWorld.Log(" 需要处理的跨服运营活动信息: cfgID=%s,isActTime=%s" % (cfgID, isActTime))
+
+ startList = [] # [startDateTime, ...]
+ endList = [] # [endDateTime, ...]
+ startNotifyDict = {} # {notifyDateTime:notifyInfo, ...}
+ endNotifyDict = {} # {notifyDateTime:notifyInfo, ...}
+ loopNotifyDict = {} # {notifyDateTime:notifyInfo, ...}
+ notifyDict = {}
+
+ # 没配置时分的代表全天
+ if not startHMStrList:
+ startDateTime = startDayDate
+ endDateTime = endDayDate
+
+ startList.append(startDateTime)
+ endList.append(endDateTime)
+
+ # 每天按时段开启的,支持多时段
+ else:
+ for hmIndex, startHMStr in enumerate(startHMStrList):
+ if hmIndex >= len(endHMStrList):
+ break
+ endHMStr = endHMStrList[hmIndex]
+ # 每天开的, 实际开关时间只取今天的日期; 这里有个问题,全服广播的时间不是今天的, 暂不做支持,之后真有这种需求再说
+ startTimeStr = "%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, startHMStr)
+ endTimeStr = "%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, endHMStr)
+ startDateTime = datetime.datetime.strptime(startTimeStr, ChConfig.TYPE_Time_Format)
+ endDateTime = datetime.datetime.strptime(endTimeStr, ChConfig.TYPE_Time_Format)
+
+ startList.append(startDateTime)
+ endList.append(endDateTime)
+
+ GameWorld.Log(" startList=%s" % (startList))
+ GameWorld.Log(" end List=%s" % (endList))
+
+ for dtIndex, startDateTime in enumerate(startList):
+ endDateTime = endList[dtIndex]
+ # 广播 - 相对实际开始时间
+ for notifyMinute, notifyInfo in notifyInfoDictStart.items():
+ notifyDateTime = startDateTime + datetime.timedelta(minutes=notifyMinute)
+ if notifyDateTime.year == curDateTime.year and notifyDateTime.month == curDateTime.month and notifyDateTime.day == curDateTime.day:
+ startNotifyDict[notifyDateTime] = notifyInfo
+
+ # 广播 - 相对实际结束时间
+ for notifyMinute, notifyInfo in notifyInfoDictEnd.items():
+ notifyDateTime = endDateTime + datetime.timedelta(minutes=notifyMinute)
+ if notifyDateTime.year == curDateTime.year and notifyDateTime.month == curDateTime.month and notifyDateTime.day == curDateTime.day:
+ endNotifyDict[notifyDateTime] = notifyInfo
+
+ # 广播 - 循环广播
+ if notifyInfoLoopInfo and len(notifyInfoLoopInfo) >= 2:
+ loopMinutes, loopNotifyKey = notifyInfoLoopInfo[:2]
+ loopNotifyParamList = notifyInfoLoopInfo[2] if len(notifyInfoLoopInfo) > 2 else []
+ notifyInfo = [loopNotifyKey, loopNotifyParamList] # 循环广播的默认无参数
+ loopCount, loopMaxCount = 0, 100
+ while loopMinutes and loopNotifyKey and loopCount < loopMaxCount:
+ loopCount += 1
+ notifyDateTime = curDateTime + datetime.timedelta(minutes=loopMinutes * loopCount)
+ if notifyDateTime >= endDateTime:
+ break
+ if notifyDateTime.year == curDateTime.year and notifyDateTime.month == curDateTime.month and notifyDateTime.day == curDateTime.day:
+ loopNotifyDict[notifyDateTime] = notifyInfo
+
+ if startNotifyDict or endNotifyDict or loopNotifyDict:
+ GameWorld.Log(" startNotifyDict: %s, %s" % (len(startNotifyDict.keys()), sorted(startNotifyDict.keys())))
+ GameWorld.Log(" end NotifyDict: %s, %s" % (len(endNotifyDict.keys()), sorted(endNotifyDict.keys())))
+ GameWorld.Log(" loop NotifyDict: %s, %s" % (len(loopNotifyDict.keys()), sorted(loopNotifyDict.keys())))
+ notifyDict.update(startNotifyDict)
+ notifyDict.update(endNotifyDict)
+ notifyDict.update(loopNotifyDict)
+
+ if actName not in actTimeInfoDict:
+ actTimeInfoDict[actName] = {}
+ actTimeInfoDict[actName][cfgID] = [ipyData, startList, endList, notifyDict]
+
+ if actName not in crossActInfoDict:
+ crossActInfoDict[actName] = {}
+ curActInfoDict = crossActInfoDict[actName]
+ if cfgID not in curActInfoDict:
+ curActInfoDict[cfgID] = {}
+ curCfgActInfoDict = curActInfoDict[cfgID]
+
+ # ipyData 活动时间表信息由跨服服务器同步子服,活动内容取子服自己的
+ ipyDataDict = {}
+ for k, v in ipyData.__dict__.items():
+ if k in ["NotifyInfoStart", "NotifyInfoEnd", "NotifyInfoLoop", "ServerIDRangeList"]:
+ continue
+ ipyDataDict[k] = v
+ ipyDataDict.update({"StartDate":startDateStr, "EndDate":endDateStr})
+ GameWorld.Log(" ipyDataDict=%s" % ipyDataDict)
+
+ curCfgActInfoDict.update({ShareDefine.ActKey_CfgID:cfgID, ShareDefine.ActKey_IpyDataInfo:ipyDataDict})
+ if ShareDefine.ActKey_ServerIDRangeList not in curCfgActInfoDict:
+ # 没有的话则使用配置中的,防止配置修改导致服务器ID分区变动引起的活动数据异常,除非后台工具强制修改
+ curCfgActInfoDict[ShareDefine.ActKey_ServerIDRangeList] = ipyData.GetServerIDRangeList()
+
+ actID, dayIndex, templateID = 0, 0, 0
+ if isActTime:
+ dayIndex = (curDateTime - startDayDate).days
+ actIDDateTime = startDayDate
+ isDayReset = 0 if not hasattr(ipyData, "GetIsDayReset") else ipyData.GetIsDayReset()
+ # 按时段开的默认每天重置
+ if isDayReset or (startHMStrList and endHMStrList):
+ actIDDateTime += datetime.timedelta(days=dayIndex)
+ actID = int(time.mktime(actIDDateTime.timetuple())) # 默认取开始时间点的time值作为活动ID
+ GameWorld.Log(" isDayReset=%s,actIDDateTime=%s,actID=%s" % (isDayReset, actIDDateTime, actID))
+
+ # 模板ID
+ if hasattr(ipyData, "TemplateIDList"):
+ templateIDList = ipyData.GetTemplateIDList()
+ templateID = templateIDList[-1] if dayIndex >= len(templateIDList) else templateIDList[dayIndex]
+
+ # 其他特殊模板ID获取处理,有需要的单独处理即可,根据活动规则自行扩展...
+
+
+ curCfgActInfoDict.update({ShareDefine.ActKey_ID:actID, ShareDefine.ActKey_TemplateID:templateID,
+ ShareDefine.ActKey_DayIndex:dayIndex})
+
+ CrossActInfo = IpyGameDataPY.SetConfigEx(key, [reloadSign, actTimeInfoDict])
+
+ GameWorld.Log("本日跨服运营活动信息加载完毕!reloadSign=%s,isRefreshState=%s" % (reloadSign, isRefreshState))
+ GameWorld.Log(" actTimeInfoDict=%s" % actTimeInfoDict)
+ GameWorld.Log(" crossActInfoDict=%s" % crossActInfoDict)
+ GameWorld.Log("=============================================================")
+ if isRefreshState:
+ Dispose_CrossActState(True)
+
+ return True, CrossActInfo
+
+def Dispose_CrossActState(reloadRefresh=False):
+
+ isReload, CrossActInfo = __GetCrossActInfo(False) # 这里必须传False
+ isReload = isReload or reloadRefresh
+ actTimeInfoDict = CrossActInfo[CrossAct_TodayInfo]
+
+ crossActInfoDict = GetCrossActInfoDict()
+
+ # 这里时间需精确到分钟,不然后面的比较会匹配不到
+ curDateTime = GameWorld.GetServerTime()
+ curDateTime = datetime.datetime.strptime("%d-%d-%d %d:%d:00" % (curDateTime.year, curDateTime.month, curDateTime.day,
+ curDateTime.hour, curDateTime.minute), ChConfig.TYPE_Time_Format)
+
+ sysnCrossActInfoDict = {}
+ for actName in ShareDefine.CrossActNameList:
+ if actName not in actTimeInfoDict or actName not in crossActInfoDict:
+ continue
+
+ for ipyData, startList, endList, notifyDict in actTimeInfoDict[actName].values():
+
+ state = 0 # 默认关闭
+ cfgID = ipyData.GetCfgID()
+
+ if cfgID not in crossActInfoDict[actName]:
+ crossActInfoDict[actName][cfgID] = {}
+ actInfoDict = crossActInfoDict[actName][cfgID]
+
+ # 状态
+ for dIndex, startDateTime in enumerate(startList):
+ endDateTime = endList[dIndex]
+ if startDateTime <= curDateTime < endDateTime:
+ state = dIndex + 1 # 也是代表第几个时间段
+ break
+
+ # 全服广播提示信息
+ if curDateTime in notifyDict:
+ serverIDRangeList = actInfoDict.get(ShareDefine.ActKey_ServerIDRangeList)
+ if serverIDRangeList != None:
+ notifyKey, paramList = notifyDict[curDateTime]
+ country = 0
+ serverGroupIDList = []
+ crossNotifyList = []
+ crossNotifyList.append([ShareDefine.CrossNotify_CrossAct, [country, notifyKey, paramList], serverIDRangeList])
+ PlayerControl.CrossNotifyEx(serverGroupIDList, crossNotifyList)
+
+ dbInfo = actInfoDict.get(ShareDefine.ActKey_DBInfo, {})
+ dbState = dbInfo.get(ShareDefine.ActKey_State, 0)
+ dbActID = dbInfo.get(ShareDefine.ActKey_ID, 0)
+ dbTemplateID = dbInfo.get(ShareDefine.ActKey_TemplateID, 0)
+
+ actID = actInfoDict.get(ShareDefine.ActKey_ID, 0)
+ templateID = actInfoDict.get(ShareDefine.ActKey_TemplateID, 0)
+ if not isReload and dbState == state and dbActID == actID:
+ #已经是这个状态了
+ continue
+ GameWorld.Log("跨服运营活动变更: actName=%s,cfgID=%s,dbState=%s -> state=%s, dbActID=%s -> actID=%s"
+ % (actName, cfgID, dbState, state, dbActID, actID))
+
+ if dbActID != actID:
+ GameWorld.Log(" 活动ID变更: actName=%s,cfgID=%s,dbActID=%s -> actID=%s,dbTemplateID=%s"
+ % (actName, cfgID, dbActID, actID, dbTemplateID))
+
+ if actName == ShareDefine.CrossActName_CTGBillboard:
+ CrossActCTGBillboard.OnActIDChange(cfgID, dbTemplateID, state)
+
+ if dbState != state:
+ pass
+
+ # 更新状态
+ actInfoDict[ShareDefine.ActKey_State] = state
+ actInfoDict[ShareDefine.ActKey_DBInfo] = {ShareDefine.ActKey_ID:actID, ShareDefine.ActKey_State:state, ShareDefine.ActKey_TemplateID:templateID}
+ GameWorld.Log(" 活动状态同步信息: actName=%s,cfgID=%s,actInfoDict=%s" % (actName, cfgID, actInfoDict))
+ if actName not in sysnCrossActInfoDict:
+ sysnCrossActInfoDict[actName] = {}
+ sysnCrossActInfoDict[actName][cfgID] = actInfoDict
+
+ # 非活动中的处理完关闭后,最后删除
+ if not state:
+ del crossActInfoDict[actName][cfgID]
+ if not crossActInfoDict[actName]:
+ del crossActInfoDict[actName]
+ GameWorld.DebugLog(" 删除结束的活动: actName=%s,cfgID=%s,crossActInfoDict=%s" % (actName, cfgID, crossActInfoDict))
+
+ # 同步子服务器
+ serverGroupIDList = []
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossActInfo, sysnCrossActInfoDict, serverGroupIDList)
+ return
+
+def Sync_CrossActInfoToClientServer(serverGroupID=0):
+ ''' 同步跨服运营活动信息到子服务器
+ @param serverGroupID: 为0时同步所有子服
+ '''
+
+ isReload, _ = __GetCrossActInfo()
+ if isReload:
+ # 如果是重读的,则在内层已经同步了,此处不重复同步
+ return
+
+ # 同步子服务器
+ sysnCrossActInfoDict = GetCrossActInfoDict()
+ serverGroupIDList = [serverGroupID] if serverGroupID else []
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossActInfo, sysnCrossActInfoDict, serverGroupIDList)
+ return
+
+## ================================================================================================
+
+def CrossServerMsg_CrossActInfo(sysnCrossActInfoDict):
+ ## 收到跨服服务器同步的跨服运营活动状态
+
+ GameWorld.Log("===== 收到跨服服务器同步的跨服运营活动状态: %s" % sysnCrossActInfoDict)
+ if PyGameData.g_crossActInfoDict == None:
+ PyGameData.g_crossActInfoDict = {}
+ PyGameData.g_crossActInfoDict.update(sysnCrossActInfoDict)
+
+ for actName, actInfoDict in sysnCrossActInfoDict.items():
+ GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossActInfo % actName, actInfoDict)
+
+ # 删除非活动中的
+ for actName, actInfoDict in PyGameData.g_crossActInfoDict.items():
+ for cfgID, actInfo in actInfoDict.items():
+ if not actInfo.get(ShareDefine.ActKey_State, 0):
+ del PyGameData.g_crossActInfoDict[actName][cfgID]
+
+ return
+
+def SendMapServerCrossActionState():
+ # 地图启动成功时通知跨服活动相关状态 - 本服地图,跨服地图不需要通知
+
+ if PyGameData.g_crossActInfoDict == None:
+ return
+
+ sysnCrossActInfoDict = PyGameData.g_crossActInfoDict
+ for actName in ShareDefine.CrossActNameList:
+ actInfoDict = sysnCrossActInfoDict.get(actName, {})
+ GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossActInfo % actName, actInfoDict)
+
+ return
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
new file mode 100644
index 0000000..b7926c8
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
@@ -0,0 +1,552 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package CrossBillboard
+#
+# @todo:跨服排行榜
+# @author hxp
+# @date 2020-01-13
+# @version 1.0
+#
+# 详细描述: 跨服排行榜
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2020-01-13 17:00"""
+#-------------------------------------------------------------------------------
+
+import CommFunc
+import ShareDefine
+import CrossRealmMsg
+import PyGameDataStruct
+import ChPyNetSendPack
+import DataRecordPack
+import NetPackCommon
+import PyDataManager
+import GameWorld
+
+import operator
+import time
+
+Def_CrossBillboard_MaxDataCount = 100 # 跨服榜单数据最大条数暂固定最大为100条,如有需要调整需针对实际情况进行评估(如数据同步、同步封包等)
+
+class CrossBillboardManager(object):
+ ## 跨服排行榜管理,注意该类只处理数据逻辑,功能相关逻辑不要写在该类,不然重读脚本不会生效
+
+ def __init__(self):
+ self.__billboardDict = {} # 排行榜字典 {(billboardType, groupValue1, groupValue2):CrossBillboard, ...}
+ return
+
+ def GetBillboardGroupList(self, bType):
+ ## 根据榜单类型获取该类型所有分组榜单信息
+ ## @return: [(billboardType, groupValue1, groupValue2), ...]
+ groupList = []
+ for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys():
+ if bType == billboardType:
+ groupList.append((billboardType, groupValue1, groupValue2))
+ return groupList
+
+ def GetCrossBillboard(self, billboardType, groupValue1, groupValue2=0):
+ ''' 获取跨服排行榜
+ @param billboardType: 排行榜类型
+ @param groupValue1: 分组值1
+ @param groupValue2: 分组值2,与分组值1组合归为同组榜单数据
+ @return: CrossBillboard
+ '''
+ key = (billboardType, groupValue1, groupValue2)
+ if key in self.__billboardDict:
+ billboardObj = self.__billboardDict[key]
+ else:
+ billboardObj = CrossBillboard(billboardType, groupValue1, groupValue2)
+ self.__billboardDict[key] = billboardObj
+ return billboardObj
+
+ # 保存数据 存数据库和realtimebackup
+ def GetSaveData(self):
+ savaData = ""
+ cntData = ""
+ cnt = 0
+ for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys():
+ billboardObj = self.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+ for i in xrange(billboardObj.GetCount()):
+ billboardData = billboardObj.At(i)
+ cnt += 1
+ savaData += billboardData.getBuffer()
+
+ GameWorld.Log("Save DBCrossBillboard cnt :%s" % cnt)
+ return CommFunc.WriteDWORD(cntData, cnt) + savaData
+
+ # 从数据库载入数据
+ def LoadPyGameData(self, datas, pos, dataslen):
+ cnt, pos = CommFunc.ReadDWORD(datas, pos)
+ GameWorld.Log("Load DBCrossBillboard cnt :%s" % cnt)
+
+ for _ in xrange(cnt):
+ billboardData = PyGameDataStruct.tagDBCrossBillboard()
+ billboardData.clear()
+ pos += billboardData.readData(datas, pos, dataslen)
+
+ billboardType, groupValue1, groupValue2 = billboardData.BillboardType, billboardData.GroupValue1, billboardData.GroupValue2
+ billboardObj = self.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+ billboardObj.AddBillboardData(billboardData)
+
+ # 排序
+ for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys():
+ billboardObj = self.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+ billboardObj.SortData()
+
+ return pos
+
+class CrossBillboard(object):
+ ''' 对应具体类型排行榜逻辑类
+ '''
+
+ def __init__(self, billboardType, groupValue1=0, groupValue2=0):
+ self.__billboardType = billboardType
+ self.__groupValue1 = groupValue1
+ self.__groupValue2 = groupValue2
+ self.__crossServerDataVer = 0 # 主服榜单数据版本
+ self.__clientServerDataVer = 0 # 子服榜单数据版本
+ self.__billboardList = [] # [tagDBCrossBillboard, ...]
+ self.__idOrderDict = {} # {id:名次, ...}
+ return
+
+ def GetBillboardType(self): return self.__billboardType
+ def GetGroupValue1(self): return self.__groupValue1
+ def GetGroupValue2(self): return self.__groupValue2
+
+ def ClearData(self):
+ GameWorld.Log("CrossBillboard ClearData billboardType=%s,groupValue1=%s,groupValue2=%s"
+ % (self.__billboardType, self.__groupValue1, self.__groupValue2))
+ self.__billboardList = [] # [tagDBCrossBillboard, ...]
+ self.__idOrderDict = {} # {id:名次, ...}
+
+ self.UpdCrossServerDataVer(0)
+ return
+
+ def SortData(self):
+ self.__billboardList.sort(key=operator.attrgetter("CmpValue", "CmpValue2", "CmpValue3"), reverse=True)
+ self.__idOrderDict = {} # 排序后重置,下次查询时更新并缓存
+ self.UpdCrossServerDataVer()
+ return
+
+ def AddBillboardData(self, billboardData):
+ ## 添加榜单数据到该榜
+ # @param billboardData: PyGameDataStruct.tagDBCrossBillboard()
+ # @return: 是否成功
+ if self.IsFull():
+ return False
+ self.__billboardList.append(billboardData)
+ return True
+
+ def FindByID(self, findID):
+ ''' 根据ID查询榜单数据
+ @param findID: 查找的ID
+ @return: None or PyGameDataStruct.tagDBCrossBillboard()
+ '''
+ idOrderDict = self.GetIDOrderDict()
+ if findID not in idOrderDict:
+ return None
+ order = idOrderDict[findID]
+ return self.__billboardList[order - 1]
+
+ def SaveDRData(self):
+ ## 记录流向数据
+ eventTypeName = "CrossBillboard_%s" % (self.__billboardType)
+ drDict = {"BillboardType":self.__billboardType, "GroupValue1":self.__groupValue1, "GroupValue2":self.__groupValue2,
+ "DataCount":len(self.__billboardList)}
+ DataRecordPack.SendEventPack(eventTypeName, drDict)
+ for billboardData in self.__billboardList:
+ dataDict = {"BillboardType":billboardData.BillboardType, "GroupValue1":billboardData.GroupValue1,
+ "GroupValue2":billboardData.GroupValue2, "Type2":billboardData.Type2,
+ "ID":billboardData.ID, "ID2":billboardData.ID2,
+ "Name1":billboardData.Name1, "Name2":billboardData.Name2,
+ "Value1":billboardData.Value1, "Value2":billboardData.Value2,
+ "CmpValue":billboardData.CmpValue, "CmpValue2":billboardData.CmpValue2,
+ "CmpValue3":billboardData.CmpValue3}
+ DataRecordPack.SendEventPack(eventTypeName, dataDict)
+ return
+
+ def GetBillboardDataList(self): return self.__billboardList
+ def GetIDOrderDict(self):
+ ## 获取ID对应名次字典
+ # @return: {ID:名次, ...} 名次从1开始
+ if not self.__idOrderDict:
+ for order, billboardData in enumerate(self.__billboardList, 1):
+ self.__idOrderDict[billboardData.ID] = order
+ return self.__idOrderDict
+
+ def GetCount(self): return len(self.__billboardList)
+ def GetMaxCount(self): return Def_CrossBillboard_MaxDataCount
+
+ def At(self, i): return self.__billboardList[i]
+ def IsFull(self): return len(self.__billboardList) >= Def_CrossBillboard_MaxDataCount
+
+ def UpdCrossServerDataVer(self, version=None):
+ ## 更新跨服榜单数据版本号,用于跨服主服、子服验证数据版本,同步榜单数据用
+ if not GameWorld.IsCrossServer():
+ return
+ if version == None:
+ version = int(time.time())
+ self.__crossServerDataVer = version
+ SyncCrossBillboardToClientServer(self.__billboardType, self.__groupValue1, self.__groupValue2)
+ return
+ def GetCrossServerDataVer(self): return self.__crossServerDataVer
+
+ def CheckClientServerDataVer(self):
+ ## 检查子服榜单数据版本是否需要同步
+ # @return: 是否需要向跨服主服同步最新数据
+ return self.__clientServerDataVer == 0 or self.__clientServerDataVer != self.__crossServerDataVer
+
+ def UpdClientServerBillboard(self, crossServerDataVer, syncBillboardList=None):
+ ## 更新本服的跨服榜单数据
+
+ # 更新跨服数据版本
+ self.__crossServerDataVer = crossServerDataVer
+ # 特殊版本0代表清除数据
+ if crossServerDataVer == 0:
+ self.ClearData()
+
+ # 更新数据
+ if syncBillboardList != None:
+ self.__billboardList = self.__billboardList[:len(syncBillboardList)] # 直接用本服以后的排行数据实例clear后覆盖更新,不足的创建新实例
+ self.__idOrderDict = {}
+ for i, syncData in enumerate(syncBillboardList):
+ ID, ID2, Name1, Name2, Type2, Value1, Value2, CmpValue, CmpValue2, CmpValue3 = syncData
+ if i < len(self.__billboardList):
+ billboardData = self.__billboardList[i]
+ billboardData.clear()
+ else:
+ billboardData = PyGameDataStruct.tagDBCrossBillboard()
+ self.__billboardList.append(billboardData)
+
+ billboardData.GroupValue1 = self.__groupValue1
+ billboardData.GroupValue2 = self.__groupValue2
+ billboardData.BillboardType = self.__billboardType
+ billboardData.ID = ID
+ billboardData.ID2 = ID2
+ billboardData.Name1 = Name1
+ billboardData.Name2 = Name2
+ billboardData.Type2 = Type2
+ billboardData.Value1 = Value1
+ billboardData.Value2 = Value2
+ billboardData.CmpValue = CmpValue
+ billboardData.CmpValue2 = CmpValue2
+ billboardData.CmpValue3 = CmpValue3
+
+ self.__idOrderDict[ID] = i + 1
+
+ self.__clientServerDataVer = crossServerDataVer
+
+ return
+
+#// C0 04 查看跨服排行榜 #tagCGViewCrossBillboard
+#
+#struct tagCGViewCrossBillboard
+#{
+# tagHead Head;
+# BYTE Type; //榜单类型
+# BYTE GroupValue1; // 分组值1
+# BYTE GroupValue2; // 分组值2,与分组值1组合归为同组榜单数据
+#};
+def OnViewCrossBillboard(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ if GameWorld.IsCrossServer():
+ return
+ playerID = curPlayer.GetPlayerID()
+ billboardType, groupValue1, groupValue2 = clientData.Type, clientData.GroupValue1, clientData.GroupValue2
+
+ if billboardType not in ShareDefine.CrossBillboardTypeList:
+ return
+
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+
+ GameWorld.DebugLog("玩家请求查看跨服排行榜: billboardType=%s,groupValue1=%s,groupValue2=%s" % (billboardType, groupValue1, groupValue2))
+ if not billboardObj.CheckClientServerDataVer():
+ SyncCrossBillboardToPlayer(curPlayer, billboardType, groupValue1, groupValue2, billboardObj.GetBillboardDataList())
+ return
+
+ # 请求查询跨服服务器
+ dataMsg = {"BillboardType":billboardType, "GroupValue1":groupValue1, "GroupValue2":groupValue2,
+ "QueryData":{"EventName":"View", "PlayerID":playerID}}
+ CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_QueryBillboard, dataMsg)
+ return
+
+def ClientServerMsg_QueryBillboard(serverGroupID, msgData):
+ ## 收到子服请求查询排行榜信息
+ billboardType = msgData["BillboardType"]
+ groupValue1 = msgData["GroupValue1"]
+ groupValue2 = msgData["GroupValue2"]
+ queryData = msgData.get("QueryData", {}) # 原数据返回子服
+ SyncCrossBillboardToClientServer(billboardType, groupValue1, groupValue2, [serverGroupID], queryData)
+ return
+
+def SyncCrossBillboardToClientServer(billboardType, groupValue1, groupValue2, serverGroupIDList=[], queryData={}):
+ ## 同步跨服榜单到子服
+ if not GameWorld.IsCrossServer():
+ return
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+ crossServerDataVer = billboardObj.GetCrossServerDataVer()
+ msgData = {"BillboardType":billboardType, "GroupValue1":groupValue1, "GroupValue2":groupValue2,
+ "QueryData":queryData, "CrossServerDataVer":crossServerDataVer}
+
+ # 有查询数据时才同步榜单数据列表,否则只同步数据版本号
+ if queryData:
+ syncBillboardList = []
+ billboardList = billboardObj.GetBillboardDataList()
+ for billboardData in billboardList:
+ ID = billboardData.ID
+ ID2 = billboardData.ID2
+ Name1 = billboardData.Name1
+ Name2 = billboardData.Name2
+ Type2 = billboardData.Type2
+ Value1 = billboardData.Value1
+ Value2 = billboardData.Value2
+ CmpValue = billboardData.CmpValue
+ CmpValue2 = billboardData.CmpValue2
+ CmpValue3 = billboardData.CmpValue3
+ syncBillboardList.append([ID, ID2, Name1, Name2, Type2, Value1, Value2, CmpValue, CmpValue2, CmpValue3])
+ msgData["BillboardDataList"] = syncBillboardList
+
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_SyncBillboard, msgData, serverGroupIDList)
+ return
+
+def CrossServerMsg_SyncBillboard(msgData, tick):
+ ## 收到跨服服务器同步的排行榜信息
+ billboardType = msgData["BillboardType"]
+ groupValue1 = msgData["GroupValue1"]
+ groupValue2 = msgData["GroupValue2"]
+ crossServerDataVer = msgData["CrossServerDataVer"]
+ syncBillboardList = msgData.get("BillboardDataList")
+ GameWorld.DebugLog("收到跨服服务器同步的排行榜信息: billboardType=%s,groupValue1=%s,groupValue2=%s,crossServerDataVer=%s"
+ % (billboardType, groupValue1, groupValue2, crossServerDataVer))
+
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+ billboardObj.UpdClientServerBillboard(crossServerDataVer, syncBillboardList)
+
+ queryData = msgData.get("QueryData")
+ if not queryData:
+ return
+
+ eventName = queryData.get("EventName")
+ eventData = queryData.get("EventData")
+ queryPlayerID = queryData.get("PlayerID", 0)
+ if not eventName or not queryPlayerID:
+ return
+
+ queryPlayer = GameWorld.GetPlayerManager().FindPlayerByID(queryPlayerID)
+ if not queryPlayer:
+ return
+
+ if eventName == "View":
+ SyncCrossBillboardToPlayer(queryPlayer, billboardType, groupValue1, groupValue2, billboardObj.GetBillboardDataList())
+ else:
+ idOrderDict = billboardObj.GetIDOrderDict()
+ order = idOrderDict.get(queryPlayerID, 0)
+ sysMsg = str([billboardType, groupValue1, groupValue2, eventName, eventData, order])
+ queryPlayer.MapServer_QueryPlayerResult(0, 0, "CrossBillboardOrder", sysMsg, len(sysMsg))
+
+ return
+
+def SyncCrossBillboardToPlayer(curPlayer, billboardType, groupValue1, groupValue2, billboardList):
+ ## 同步给玩家跨服榜单
+ billboardInfo = ChPyNetSendPack.tagGCCrossBillboardInfo()
+ billboardInfo.Type = billboardType
+ billboardInfo.GroupValue1 = groupValue1
+ billboardInfo.GroupValue2 = groupValue2
+ billboardInfo.CrossBillboardDataList = []
+ for billboardData in billboardList:
+ billboardInfoData = ChPyNetSendPack.tagGCCrossBillboardData()
+ billboardInfoData.ID = billboardData.ID
+ billboardInfoData.Name1 = billboardData.Name1
+ billboardInfoData.Name2 = billboardData.Name2
+ billboardInfoData.Type2 = billboardData.Type2
+ billboardInfoData.Value1 = billboardData.Value1
+ billboardInfoData.Value2 = billboardData.Value2
+ billboardInfoData.CmpValue = billboardData.CmpValue
+ billboardInfoData.CmpValue2 = billboardData.CmpValue2
+ billboardInfoData.CmpValue3 = billboardData.CmpValue3
+ billboardInfo.CrossBillboardDataList.append(billboardInfoData)
+ billboardInfo.BillboardCount = len(billboardInfo.CrossBillboardDataList)
+ NetPackCommon.SendFakePack(curPlayer, billboardInfo)
+ return
+
+def MapServer_UpdateCrossBillboard(billInfoDict):
+ '''地图更新跨服排行榜, 通用
+ {"Type":bType, "GroupValue1":groupValue1, "Type2":type2, "ID":dataID, "ID2":id2, "Name1":name1, "Name2":name2,
+ "Value1":value1, "Value2":value2, "CmpValue":cmpValue, "CmpValue2":cmpValue2, "CmpValue3":cmpValue3,
+ "GroupValue2":groupValue2}
+ '''
+
+ if GameWorld.IsCrossServer():
+ # 只有子服务器能调用
+ return
+ GameWorld.DebugLog("子服地图更新跨服榜单数据! %s" % billInfoDict)
+
+ billboardType = billInfoDict["Type"]
+ if billboardType not in ShareDefine.CrossBillboardTypeList:
+ return
+ groupValue1 = billInfoDict["GroupValue1"]
+ groupValue2 = billInfoDict["GroupValue2"]
+ dataID = billInfoDict["ID"]
+ if not groupValue1 or not dataID:
+ return
+
+ type2 = billInfoDict["Type2"]
+ id2 = billInfoDict["ID2"]
+ name1 = billInfoDict["Name1"]
+ name2 = billInfoDict["Name2"]
+ value1 = billInfoDict["Value1"]
+ value2 = billInfoDict["Value2"]
+ cmpValue = billInfoDict["CmpValue"]
+ cmpValue2 = billInfoDict["CmpValue2"]
+ cmpValue3 = billInfoDict["CmpValue3"]
+
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+ billboardData = billboardObj.FindByID(dataID)
+ if billboardData:
+ if cmpValue == billboardData.CmpValue and cmpValue2 == billboardData.CmpValue2 \
+ and (not cmpValue3 or cmpValue3 == billboardData.CmpValue3) \
+ and value1 == billboardData.Value1 and value2 == billboardData.Value2 \
+ and name1 == billboardData.Name1 and name2 == billboardData.Name2 \
+ and type2 == billboardData.Type2 and id2 == billboardData.ID2:
+ GameWorld.DebugLog(" 榜单值相同,不同步跨服服务器! ")
+ return
+
+ elif billboardObj.IsFull():
+ lastBillBoardData = __CmpLastBillboardData(cmpValue, cmpValue2, cmpValue3, billboardObj)
+ if not lastBillBoardData:
+ GameWorld.DebugLog(" 榜单值不超过最后一名,不同步跨服服务器! ")
+ return
+
+ else:
+ GameWorld.DebugLog(" 本服没有在榜上!")
+
+ # 同步跨服服务器
+ CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_UpdateBillboard, billInfoDict)
+ return
+
+def ClientServerMsg_UpdateBillboard(serverGroupID, billInfoDict):
+ GameWorld.Log("收到子服更新跨服榜单数据! serverGroupID=%s, %s" % (serverGroupID, billInfoDict))
+
+ billboardType = billInfoDict["Type"]
+ if billboardType not in ShareDefine.CrossBillboardTypeList:
+ return
+ groupValue1 = billInfoDict["GroupValue1"]
+ groupValue2 = billInfoDict["GroupValue2"]
+
+ type2 = billInfoDict["Type2"]
+ dataID = billInfoDict["ID"]
+ id2 = billInfoDict["ID2"]
+ name1 = billInfoDict["Name1"]
+ name2 = billInfoDict["Name2"]
+ value1 = billInfoDict["Value1"]
+ value2 = billInfoDict["Value2"]
+ cmpValue = billInfoDict["CmpValue"]
+ cmpValue2 = billInfoDict["CmpValue2"]
+ cmpValue3 = billInfoDict["CmpValue3"]
+
+ UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2,
+ cmpValue, cmpValue2, cmpValue3, groupValue2, id2)
+ return
+
+def UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,
+ cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, autoSort=True):
+ ''' 更新跨服排行榜
+ @param billboardType: 排行榜索引类型,同个榜单类型可以有多个分组榜单数据,独立排序
+ @param groupValue1: 榜单分组1
+ @param dataID: 榜单唯一数据ID,如玩家ID等
+ @param name1: 显示名称1,不影响排序
+ @param name2: 显示名称2,不影响排序
+ @param type2: 榜单数据类型2,自定义,一般为职业等二级分类,不影响排序
+ @param value1: 显示值1,不影响排序
+ @param value2: 显示值2,不影响排序
+ @param cmpValue: 比较值1
+ @param cmpValue2: 比较值2
+ @param cmpValue3: 比较值3,没设定的话默认为时间戳比较值
+ @param groupValue1: 榜单分组2
+ @param id2: 扩展数据ID2
+ @param autoSort: 是否排序,默认True
+ @return: 是否上榜更新榜单
+ '''
+ if not GameWorld.IsCrossServer():
+ # 只有跨服服务器能调用
+ return
+ if not groupValue1 or not dataID:
+ return
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+ billboardData = billboardObj.FindByID(dataID)
+ isNewData = False
+ if not billboardData:
+ isNewData = True
+ if billboardObj.IsFull():
+ # 与最后一名对比
+ lastBillBoardData = __CmpLastBillboardData(cmpValue, cmpValue2, cmpValue3, billboardObj)
+ if not lastBillBoardData:
+ GameWorld.DebugLog(" 榜单值不超过最后一名,不上榜! ")
+ return
+ billboardData = lastBillBoardData
+ billboardData.clear()
+ else:
+ billboardData = PyGameDataStruct.tagDBCrossBillboard()
+ if not billboardObj.AddBillboardData(billboardData):
+ return
+
+ # 没设置值默认为时间time,先上榜的排前面
+ if cmpValue3 == 0:
+ # 时间权值仅在比较值变更的情况下才更新, 防止其他附属值更新时导致比较值相同的玩家名次间会变动的问题
+ if isNewData or billboardData.CmpValue != cmpValue or billboardData.CmpValue2 != cmpValue2:
+ calcTime = GameWorld.ChangeTimeStrToNum("2090-01-01 00:00:00")
+ cmpValue3 = max(0, calcTime - int(time.time())) # 比较值3如果没指定值则默认存当前更新的time
+ else:
+ cmpValue3 = billboardData.CmpValue3
+
+ cmpValueChange = billboardData.CmpValue != cmpValue or billboardData.CmpValue2 != cmpValue2 or billboardData.CmpValue3 != cmpValue3
+
+ # 更新所有值
+ billboardData.GroupValue1 = groupValue1
+ billboardData.GroupValue2 = groupValue2
+ billboardData.BillboardType = billboardType
+ billboardData.ID = dataID
+ billboardData.ID2 = id2
+ billboardData.Name1 = name1
+ billboardData.Name2 = name2
+ billboardData.Type2 = type2
+ billboardData.Value1 = value1
+ billboardData.Value2 = value2
+ billboardData.CmpValue = cmpValue
+ billboardData.CmpValue2 = cmpValue2
+ billboardData.CmpValue3 = cmpValue3
+
+ GameWorld.DebugLog("更新跨服排行榜值: billboardType=%s,groupValue1=%s,groupValue2=%s,dataID=%s,isNewData=%s,cmpValueChange=%s,type2=%s,value1=%s,value2=%s,cmpValue=%s,cmpValue2=%s,cmpValue3=%s"
+ % (billboardType, groupValue1, groupValue2, dataID, isNewData, cmpValueChange,
+ type2, value1, value2, cmpValue, cmpValue2, cmpValue3), dataID)
+
+ if autoSort and cmpValueChange:
+ billboardObj.SortData()
+ else:
+ billboardObj.UpdCrossServerDataVer()
+ return True
+
+def __CmpLastBillboardData(cmpValue, cmpValue2, cmpValue3, billboardObj):
+ ## 比较是否超过最后一名
+ # @return: 超过则返回最后一名数据实例,否则返回None
+ if not billboardObj.GetCount():
+ return
+ lastBillBoardData = billboardObj.At(billboardObj.GetCount() - 1)
+ if cmpValue < lastBillBoardData.CmpValue:
+ #无法上榜
+ return
+ elif cmpValue == lastBillBoardData.CmpValue:
+ if cmpValue2 < lastBillBoardData.CmpValue2:
+ return
+ elif cmpValue2 == lastBillBoardData.CmpValue2:
+ if cmpValue3 <= lastBillBoardData.CmpValue3:
+ return
+ return lastBillBoardData
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
index d660881..05939f6 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
@@ -21,6 +21,8 @@
import IPY_GameServer
import CrossRealmPlayer
import PlayerCompensation
+import CrossActionControl
+import CrossBillboard
import GameWorldBoss
import CrossRealmPK
import PlayerQuery
@@ -79,7 +81,16 @@
elif msgType == ShareDefine.ClientServerMsg_PKBillboard:
CrossRealmPK.ClientServerMsg_PKBillboard(serverGroupID, msgData)
-
+
+ elif msgType == ShareDefine.ClientServerMsg_QueryBillboard:
+ CrossBillboard.ClientServerMsg_QueryBillboard(serverGroupID, msgData)
+
+ elif msgType == ShareDefine.ClientServerMsg_UpdateBillboard:
+ CrossBillboard.ClientServerMsg_UpdateBillboard(serverGroupID, msgData)
+
+ elif msgType == ShareDefine.ClientServerMsg_MailContent:
+ PlayerCompensation.ClientServerMsg_MailContent(serverGroupID, msgData, tick)
+
elif msgType == ShareDefine.ClientServerMsg_ChatCrossWorld:
PlayerTalk.ClientServerMsg_ChatCrossWorld(serverGroupID, msgData, tick)
@@ -136,6 +147,8 @@
CrossRealmPlayer.Sync_CrossCommInitDataToClientServer(serverGroupID)
CrossRealmPK.Sync_CrossPKInitDataToClientServer(tick, serverGroupID)
CrossBoss.Sync_CrossBossInitDataToClientServer(serverGroupID)
+ CrossActionControl.Sync_CrossActInfoToClientServer(serverGroupID)
+ PlayerCompensation.Sync_CrossMailPlayerIDToClientServer(serverGroupID)
return
def MapServer_CrossServerReceiveMsg(msgType, msgData, serverGroupID):
@@ -253,11 +266,17 @@
elif msgType == ShareDefine.CrossServerMsg_PKSyncBillboard:
CrossRealmPK.CrossServerMsg_PKSyncBillboard(msgData)
+ elif msgType == ShareDefine.CrossServerMsg_SyncBillboard:
+ CrossBillboard.CrossServerMsg_SyncBillboard(msgData, tick)
+
elif msgType == ShareDefine.CrossServerMsg_CrossBossInfo:
CrossBoss.CrossServerMsg_CrossBossInfo(msgData)
elif msgType == ShareDefine.CrossServerMsg_CrossBossState:
CrossBoss.CrossServerMsg_CrossBossState(msgData)
+
+ elif msgType == ShareDefine.CrossServerMsg_CrossActInfo:
+ CrossActionControl.CrossServerMsg_CrossActInfo(msgData)
elif msgType == ShareDefine.CrossServerMsg_PutInItem:
CrossRealmPlayer.CrossServerMsg_PutInItem(msgData)
@@ -277,6 +296,12 @@
elif msgType == ShareDefine.CrossServerMsg_SendMail:
PlayerCompensation.CrossServerMsg_SendMail(msgData)
+ elif msgType == ShareDefine.CrossServerMsg_MailPlayerIDList:
+ PlayerCompensation.CrossServerMsg_MailPlayerIDList(msgData)
+
+ elif msgType == ShareDefine.CrossServerMsg_MailContent:
+ PlayerCompensation.CrossServerMsg_MailContent(msgData)
+
elif msgType == ShareDefine.CrossServerMsg_FBPlayerCount:
PlayerFB.CrossServerMsg_FBPlayerCount(msgData)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
index e75d064..0ef4888 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
@@ -37,6 +37,7 @@
import GameWorldAverageLv
import PlayerFamilyBoss
import PlayerHorsePetBoss
+import CrossActionControl
import GameWorldProcess
import ChPyNetSendPack
import NetPackCommon
@@ -106,6 +107,7 @@
if GameWorld.IsCrossServer():
# 跨服不处理运营活动
return
+ CrossActionControl.SendMapServerCrossActionState()
isReload, OperationActionInfo = __GetOperationActionInfo()
mapServerInfoDict = OperationActionInfo[OperationAction_MapServerInfo]
@@ -506,6 +508,7 @@
if GameWorld.IsCrossServer():
# 跨服不处理运营活动
+ CrossActionControl.Dispose_CrossActState(reloadRefresh)
return
isReload, OperationActionInfo = __GetOperationActionInfo(False) # 这里必须传False
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index 1ea80b1..0516bb5 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -624,6 +624,27 @@
("WORD", "LVLimit", 0),
),
+ "CrossActCTGBillboard":(
+ ("DWORD", "CfgID", 1),
+ ("char", "ActGroupName", 0),
+ ("list", "ServerIDRangeList", 0),
+ ("char", "StartDate", 0),
+ ("char", "EndDate", 0),
+ ("dict", "NotifyInfoStart", 0),
+ ("dict", "NotifyInfoEnd", 0),
+ ("list", "NotifyInfoLoop", 0),
+ ("BYTE", "IsDayReset", 0),
+ ("list", "TemplateIDList", 0),
+ ),
+
+ "CrossActCTGBillboardOrder":(
+ ("DWORD", "TemplateID", 1),
+ ("WORD", "OrderA", 0),
+ ("WORD", "OrderB", 0),
+ ("DWORD", "CTGAtleast", 0),
+ ("list", "AwardItemList", 0),
+ ),
+
"EquipStarUp":(
("BYTE", "ClassLV", 1),
("BYTE", "EquipPlace", 1),
@@ -1892,6 +1913,50 @@
def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
def GetLVLimit(self): return self.LVLimit # 限制等级
+# 跨服充值排行活动时间表
+class IPY_CrossActCTGBillboard():
+
+ def __init__(self):
+ self.CfgID = 0
+ self.ActGroupName = ""
+ self.ServerIDRangeList = []
+ self.StartDate = ""
+ self.EndDate = ""
+ self.NotifyInfoStart = {}
+ self.NotifyInfoEnd = {}
+ self.NotifyInfoLoop = []
+ self.IsDayReset = 0
+ self.TemplateIDList = []
+ return
+
+ def GetCfgID(self): return self.CfgID # 配置ID
+ def GetActGroupName(self): return self.ActGroupName # 活动组名(同组活动的名字需相同)
+ def GetServerIDRangeList(self): return self.ServerIDRangeList # 活动的账号服务器ID范围列表 [[serverIDA, serverIDB], ...]
+ def GetStartDate(self): return self.StartDate # 开启日期
+ def GetEndDate(self): return self.EndDate # 结束日期
+ def GetNotifyInfoStart(self): return self.NotifyInfoStart # 全服提示信息 - 相对开始时间
+ def GetNotifyInfoEnd(self): return self.NotifyInfoEnd # 全服提示信息 - 相对结束时间
+ def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[循环分钟, 广播key, [广播参数列表可选]]
+ def GetIsDayReset(self): return self.IsDayReset # 是否每天重置
+ def GetTemplateIDList(self): return self.TemplateIDList # 模板ID列表
+
+# 跨服充值排行模板名次奖励表
+class IPY_CrossActCTGBillboardOrder():
+
+ def __init__(self):
+ self.TemplateID = 0
+ self.OrderA = 0
+ self.OrderB = 0
+ self.CTGAtleast = 0
+ self.AwardItemList = []
+ return
+
+ def GetTemplateID(self): return self.TemplateID # 模板ID
+ def GetOrderA(self): return self.OrderA # 名次A
+ def GetOrderB(self): return self.OrderB # 至名次B
+ def GetCTGAtleast(self): return self.CTGAtleast # 至少充值RMB
+ def GetAwardItemList(self): return self.AwardItemList # 奖励物品列表[[物品ID,个数,是否拍品], ...]
+
# 装备升星表
class IPY_EquipStarUp():
@@ -2084,6 +2149,10 @@
self.ipyNewUniquenessArriveLen = len(self.ipyNewUniquenessArriveCache)
self.ipyActLuckyTreasureCache = self.__LoadFileData("ActLuckyTreasure", IPY_ActLuckyTreasure)
self.ipyActLuckyTreasureLen = len(self.ipyActLuckyTreasureCache)
+ self.ipyCrossActCTGBillboardCache = self.__LoadFileData("CrossActCTGBillboard", IPY_CrossActCTGBillboard)
+ self.ipyCrossActCTGBillboardLen = len(self.ipyCrossActCTGBillboardCache)
+ self.ipyCrossActCTGBillboardOrderCache = self.__LoadFileData("CrossActCTGBillboardOrder", IPY_CrossActCTGBillboardOrder)
+ self.ipyCrossActCTGBillboardOrderLen = len(self.ipyCrossActCTGBillboardOrderCache)
self.ipyEquipStarUpCache = self.__LoadFileData("EquipStarUp", IPY_EquipStarUp)
self.ipyEquipStarUpLen = len(self.ipyEquipStarUpCache)
self.ipyFamilyWarRankAwardCache = self.__LoadFileData("FamilyWarRankAward", IPY_FamilyWarRankAward)
@@ -2368,6 +2437,10 @@
def GetNewUniquenessArriveByIndex(self, index): return self.ipyNewUniquenessArriveCache[index]
def GetActLuckyTreasureCount(self): return self.ipyActLuckyTreasureLen
def GetActLuckyTreasureByIndex(self, index): return self.ipyActLuckyTreasureCache[index]
+ def GetCrossActCTGBillboardCount(self): return self.ipyCrossActCTGBillboardLen
+ def GetCrossActCTGBillboardByIndex(self, index): return self.ipyCrossActCTGBillboardCache[index]
+ def GetCrossActCTGBillboardOrderCount(self): return self.ipyCrossActCTGBillboardOrderLen
+ def GetCrossActCTGBillboardOrderByIndex(self, index): return self.ipyCrossActCTGBillboardOrderCache[index]
def GetEquipStarUpCount(self): return self.ipyEquipStarUpLen
def GetEquipStarUpByIndex(self, index): return self.ipyEquipStarUpCache[index]
def GetFamilyWarRankAwardCount(self): return self.ipyFamilyWarRankAwardLen
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py
index 876684c..84c3f33 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py
@@ -28,12 +28,16 @@
import NetPackCommon
import CommFunc
import ChPyNetSendPack
+import PyGameDataStruct
+import CrossRealmMsg
import DataRecordPack
import ReadChConfig
import PlayerDBOper
import EventReport
import IpyGameDataPY
import PlayerControl
+import PyDataManager
+import PyGameData
import datetime
import uuid
import math
@@ -68,6 +72,216 @@
Def_RequestState = "CompensationRequestState"
+#==================================================================================================
+class CrossPersonalCompensationManager(object):
+ ## 跨服邮件管理,注意该类只处理数据逻辑,功能相关逻辑不要写在该类,不然重读脚本不会生效
+
+ def __init__(self):
+ self.playerMailDict = {} # 玩家补偿列表 {playerID:{GUID:tagDBCrossPersonalCompensation, ...}, ...}
+ return
+
+ # 保存数据 存数据库和realtimebackup
+ def GetSaveData(self):
+ savaData = ""
+ cntData = ""
+ cnt = 0
+ for mailDict in self.playerMailDict.values():
+ for mailObj in mailDict.values():
+ cnt += 1
+ savaData += mailObj.getBuffer()
+
+ GameWorld.Log("Save DBCrossPersonalCompensation cnt :%s" % cnt)
+ return CommFunc.WriteDWORD(cntData, cnt) + savaData
+
+ # 从数据库载入数据
+ def LoadPyGameData(self, datas, pos, dataslen):
+ cnt, pos = CommFunc.ReadDWORD(datas, pos)
+ GameWorld.Log("Load DBCrossPersonalCompensation cnt :%s" % cnt)
+
+ for _ in xrange(cnt):
+ mailObj = PyGameDataStruct.tagDBCrossPersonalCompensation()
+ mailObj.clear()
+ pos += mailObj.readData(datas, pos, dataslen)
+
+ playerID = mailObj.PlayerID
+ guid = mailObj.GUID
+ if playerID not in self.playerMailDict:
+ self.playerMailDict[playerID] = {}
+ mailDict = self.playerMailDict[playerID]
+ mailDict[guid] = mailObj
+
+ return pos
+
+def Sync_CrossMailPlayerIDToClientServer(serverGroupID=0):
+ ''' 同步有跨服邮件的玩家ID到子服
+ @param serverGroupID: 为0时同步所有子服
+ '''
+ crossMailMgr = PyDataManager.GetCrossPersonalCompensationManager()
+ addMailPlayerIDList = crossMailMgr.playerMailDict.keys()
+ if not addMailPlayerIDList:
+ return
+ # 同步子服务器
+ serverGroupIDList = [serverGroupID] if serverGroupID else []
+ dataMsg = {"IDType":"Add", "PlayerIDList":addMailPlayerIDList}
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_MailPlayerIDList, dataMsg, serverGroupIDList)
+ return
+
+def CrossServerMsg_MailPlayerIDList(dataMsg):
+ ## 收到跨服服务器同步有跨服邮件的玩家ID列表
+ idType = dataMsg["IDType"]
+ playerIDList = dataMsg["PlayerIDList"]
+ for playerID in playerIDList:
+ if idType == "Del":
+ if playerID in PyGameData.g_crossMailPlayerDict:
+ PyGameData.g_crossMailPlayerDict.pop(playerID)
+ continue
+
+ if idType == "Add":
+ if playerID in PyGameData.g_crossMailPlayerDict:
+ continue
+ PyGameData.g_crossMailPlayerDict[playerID] = 0
+
+ player = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+ if not player or not player.GetInitOK():
+ continue
+ RequestToGetCrossMail(player)
+
+ return
+
+def RequestToGetCrossMail(curPlayer):
+ ## 请求同步跨服邮件内容
+ playerID = curPlayer.GetPlayerID()
+ if playerID not in PyGameData.g_crossMailPlayerDict:
+ return
+ lastTick = PyGameData.g_crossMailPlayerDict[playerID]
+ tick = GameWorld.GetGameWorld().GetTick()
+ if tick - lastTick <= 30000:
+ return
+ PyGameData.g_crossMailPlayerDict[playerID] = tick
+ dataMsg = {"CMD":"Get", "PlayerID":playerID}
+ CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_MailContent, dataMsg)
+ return
+
+def ClientServerMsg_MailContent(serverGroupID, msgData, tick):
+ ## 收到子服玩家请求同步跨服邮件
+
+ GameWorld.Log("收到子服玩家同步个人邮件命令: serverGroupID=%s, %s" % (serverGroupID, msgData))
+
+ reqCMD = msgData["CMD"]
+ playerID = msgData["PlayerID"]
+ guidList = msgData.get("GuidList", [])
+ crossMailMgr = PyDataManager.GetCrossPersonalCompensationManager()
+ if playerID not in crossMailMgr.playerMailDict:
+ return
+ playerMailDict = crossMailMgr.playerMailDict[playerID]
+
+ if reqCMD == "Get":
+ SyncTickAttrKey = "SyncTick"
+ getMailList = []
+ for guid, mailObj in playerMailDict.items():
+ if hasattr(mailObj, SyncTickAttrKey):
+ getTick = getattr(mailObj, SyncTickAttrKey)
+ if tick - getTick <= 30000:
+ GameWorld.DebugLog("短时间内重复请求领取的邮件不同步,防止重复发放! GUID=%s" % guid)
+ continue
+ setattr(mailObj, SyncTickAttrKey, tick)
+ crossMailDict = {"PlayerID":mailObj.PlayerID, "GUID":mailObj.GUID, "LimitTime":mailObj.LimitTime,
+ "Text":mailObj.Text, "ItemInfo":mailObj.ItemInfo, "Detail":mailObj.Detail,
+ "Gold":mailObj.Gold, "GoldPaper":mailObj.GoldPaper, "Silver":mailObj.Silver,
+ "MoneySource":mailObj.MoneySource
+ }
+ getMailList.append(crossMailDict)
+
+ if getMailList:
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_MailContent, getMailList, [serverGroupID])
+
+ elif reqCMD == "GetOK":
+
+ for guid in guidList:
+ playerMailDict.pop(guid, None)
+ DataRecordPack.DR_GiveCompensationSuccess(playerID, guid)
+
+ if not playerMailDict:
+ crossMailMgr.playerMailDict.pop(playerID, None)
+ dataMsg = {"IDType":"Del", "PlayerIDList":[playerID]}
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_MailPlayerIDList, dataMsg, [serverGroupID])
+
+ return
+
+def CrossServerMsg_MailContent(getMailList):
+ ## 收到跨服服务器同步的待发送邮件内容
+
+ playerGetGUIDInfo = {}
+ for mailDict in getMailList:
+ GUID = mailDict.get("GUID", "")
+ playerID = mailDict.get("PlayerID", 0)
+ if not GUID or not playerID:
+ continue
+
+ GameWorld.Log("收到跨服个人邮件内容:%s" % mailDict, playerID)
+
+ addItemDictList = eval(mailDict.get("ItemInfo", "[]"))
+ LimitTime = mailDict.get("LimitTime", "")
+ Text = mailDict.get("Text", "")
+ gold = GameWorld.ToIntDef(mailDict.get("Gold"))
+ goldPaper = GameWorld.ToIntDef(mailDict.get("GoldPaper"))
+ silver = GameWorld.ToIntDef(mailDict.get("Silver"))
+ moneySource = GameWorld.ToIntDef(mailDict.get("MoneySource"), ChConfig.Def_GiveMoney_Mail)
+ detail = mailDict.get("Detail", "")
+
+ AddPersonalItem(GUID, addItemDictList, [playerID], LimitTime, Text, gold, goldPaper, silver, detail, moneySource)
+
+ if playerID not in playerGetGUIDInfo:
+ playerGetGUIDInfo[playerID] = []
+ guidList = playerGetGUIDInfo[playerID]
+ guidList.append(GUID)
+
+ for playerID, guidList in playerGetGUIDInfo.items():
+ dataMsg = {"CMD":"GetOK", "PlayerID":playerID, "GuidList":guidList}
+ CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_MailContent, dataMsg)
+
+ return
+
+def __AddPlayerCrossMail(addItemDictList, PlayerIDList, LimitTime, Text, gold, goldPaper, silver, detail, moneySource):
+ ## 添加跨服玩家个人补偿邮件
+
+ addMailPlayerIDList = []
+ crossMailMgr = PyDataManager.GetCrossPersonalCompensationManager()
+ for playerID in PlayerIDList:
+ GUID = str(uuid.uuid1()) # 由于跨服邮件由每个玩家独自同步个人邮件,所以插入时每个人的邮件单独GUID,防止批量发送同内容邮件时重复插入奖励物品
+ mailObj = PyGameDataStruct.tagDBCrossPersonalCompensation()
+ mailObj.PlayerID = playerID
+ mailObj.GUID = GUID
+ mailObj.LimitTime = LimitTime
+ mailObj.Text = Text
+ mailObj.TextLen = len(mailObj.Text)
+ mailObj.Gold = gold
+ mailObj.GoldPaper = goldPaper
+ mailObj.Silver = silver
+ mailObj.ItemInfo = json.dumps(addItemDictList, ensure_ascii=False)
+ mailObj.ItemLen = len(mailObj.ItemInfo)
+ mailObj.Detail = detail
+ mailObj.DetailLen = len(mailObj.Detail)
+ mailObj.MoneySource = moneySource
+
+ if playerID not in crossMailMgr.playerMailDict:
+ crossMailMgr.playerMailDict[playerID] = {}
+ addMailPlayerIDList.append(playerID)
+ playerMailDict = crossMailMgr.playerMailDict[playerID]
+ playerMailDict[GUID] = mailObj
+
+ #添加流向
+ addDict = {"LimitTime":LimitTime, "Text":Text, "Gold":gold, "GoldPaper":goldPaper, "Silver":silver,
+ "ItemListLen":len(addItemDictList), "Detail":detail, "MoneySource":moneySource, "CrossMail":True}
+ DataRecordPack.DR_AddPersonalCompensation(PlayerIDList, GUID, addItemDictList, addDict)
+
+ if addMailPlayerIDList:
+ dataMsg = {"IDType":"Add", "PlayerIDList":addMailPlayerIDList}
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_MailPlayerIDList, dataMsg)
+
+ return
+
+#==================================================================================================
## 根据物品信息字典,生成补偿物品实例,用于GM工具添加补偿
# @param curItemDict
# @return IpyCompensationItem
@@ -86,10 +300,10 @@
# @param addItemList [(itemID, itemCnt, 是否拍品), {或物品信息字典}, ...]
# @return GUID
def SendPersonalItemMailEx(title, content, getDays, playerIDList, addItemList, gold = 0, goldPaper = 0, silver = 0,
- detail="", moneySource=ChConfig.Def_GiveMoney_Mail):
+ detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):
limitTime = str(GameWorld.GetDatetimeByDiffDays(getDays))
limitTime = limitTime.split(".")[0]
- return SendPersonalItemMail(title, content, limitTime, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource)
+ return SendPersonalItemMail(title, content, limitTime, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource, crossMail)
def SendPersonalItemMailBatch(batchMailInfoList):
## 批量发送邮件
@@ -123,14 +337,14 @@
return
def SendMailByKey(mailTypeKey, playerIDList, addItemList, paramList=[], gold=0, goldPaper=0, silver=0,
- detail="", moneySource=ChConfig.Def_GiveMoney_Mail):
+ detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):
if not mailTypeKey:
mailTypeKey = ShareDefine.DefaultLackSpaceMailType
GameWorld.DebugLog("SendMailByKey %s, playerIDList=%s, addItemList=%s, paramList=%s, gold=%s, goldPaper=%s, silver=%s, moneySource=%s"
% (mailTypeKey, playerIDList, addItemList, paramList, gold, goldPaper, silver, moneySource))
title = ""
content = "<MailTemplate>%s</MailTemplate>%s" % (mailTypeKey, json.dumps(paramList, ensure_ascii=False))
- return SendPersonalItemMailEx(title, content, 30, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource)
+ return SendPersonalItemMailEx(title, content, 30, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource, crossMail)
def CrossServerMsg_SendMail(msgData):
## 收到跨服服务器同步的发送邮件
@@ -147,7 +361,7 @@
# @return GUID
# @remarks addItemList支持append字典
def SendPersonalItemMail(title, content, limitTime, playerIDList, addItemList, gold = 0, goldPaper = 0, silver = 0,
- detail="", moneySource=ChConfig.Def_GiveMoney_Mail):
+ detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):
if not playerIDList:
return ""
@@ -185,7 +399,7 @@
GUID = str(uuid.uuid1())
AddPersonalItem(GUID, addItemDictList[startIndex:startIndex + perMailItemCnt], playerIDList,
limitTime, "%s<$_$>%s<$_$>%s" % (ChConfig.Def_Mail_SenderSys, title, content),
- gold, goldPaper, silver, detail, moneySource)
+ gold, goldPaper, silver, detail, moneySource, crossMail)
return GUID
## 发送纯文字个人补偿
@@ -514,8 +728,11 @@
## 添加个人补偿
# @param addItemDict, PlayerIDList, LimitTime, Text
# @return None
-def AddPersonalItem(GUID, addItemDictList, PlayerIDList, LimitTime, Text, gold = 0, goldPaper = 0, silver = 0, detail="", moneySource=ChConfig.Def_GiveMoney_Mail):
+def AddPersonalItem(GUID, addItemDictList, PlayerIDList, LimitTime, Text, gold = 0, goldPaper = 0, silver = 0,
+ detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):
if GameWorld.IsCrossServer():
+ if crossMail:
+ __AddPlayerCrossMail(addItemDictList, PlayerIDList, LimitTime, Text, gold, goldPaper, silver, detail, moneySource)
return
GameWorld.DebugLog("Compensation### AddPersonalItem GUID:%s ItemDict:\n%s "%(GUID, addItemDictList))
@@ -633,6 +850,7 @@
# 提取接收邮件下发
def NotifyPlayerCompensation(curPlayer):
+ RequestToGetCrossMail(curPlayer)
notifyList = SeekPlayerCompensation(curPlayer)
SyncQueryCompensationResult(curPlayer, notifyList)
return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
index fc99fab..992828b 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
@@ -71,16 +71,47 @@
CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_Notify, crossNotifyList, serverGroupIDList)
return
+def CrossNotifyEx(serverGroupIDList, crossNotifyList):
+ ''' 跨服广播信息提示,支持同步多条,同时也建议多条一起同步
+ @param serverGroupIDList: 需要同步到的目标服务器组ID列表
+ @param crossNotifyList: 信息提示列表,[[notifyType, paramsList, 自定义扩展信息], ...] notifyType 如 ShareDefine.CrossNotify_CrossAct
+ '''
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_Notify, crossNotifyList, serverGroupIDList)
+ return
+
def CrossServerMsg_Notify(crossNotifyList):
GameWorld.DebugLog("收到跨服同步的广播提示内容: count=%s" % len(crossNotifyList))
for notifyInfo in crossNotifyList:
- if "Type" not in notifyInfo or "Params" not in notifyInfo:
+ if isinstance(notifyInfo, dict):
+ if "Type" not in notifyInfo or "Params" not in notifyInfo:
+ continue
+ notifyType = notifyInfo["Type"]
+ params = notifyInfo["Params"]
+ elif isinstance(notifyInfo, list) and len(notifyInfo) >= 2:
+ notifyType, params = notifyInfo[:2]
+ else:
continue
- notifyType = notifyInfo["Type"]
- params = notifyInfo["Params"]
+
if notifyType == ShareDefine.CrossNotify_World:
country, msgMark, msgParamList = params
WorldNotify(country, msgMark, msgParamList)
+ elif notifyType == ShareDefine.CrossNotify_CrossAct:
+ country, msgMark, msgParamList = params
+ serverIDRangeList = notifyInfo[2]
+ playerManager = GameWorld.GetPlayerManager()
+ for i in xrange(playerManager.GetPlayerCount()):
+ curPlayer = playerManager.GetPlayerByIndex(i)
+ if curPlayer == None or not curPlayer.GetInitOK() or GetIsTJG(curPlayer):
+ continue
+ if not serverIDRangeList:
+ NotifyCode(curPlayer, msgMark, msgParamList)
+ return
+ playerServerID = GameWorld.GetPlayerServerID(curPlayer)
+ for serverIDA, serverIDB in serverIDRangeList:
+ if serverIDA <= playerServerID <= serverIDB:
+ NotifyCode(curPlayer, msgMark, msgParamList)
+ break
+
elif notifyType == ShareDefine.CrossNotify_Family:
familyID, msgMark, msgParamList = params
FamilyNotify(familyID, msgMark, msgParamList)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
index 1f74503..90f94aa 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
@@ -139,6 +139,8 @@
# 服务器建盟次数
Def_ServerCreatFamilyTimes = "CreatFamilyTimes"
+#设置跨服运营活动ID的标记
+Def_CrossActID = 'CAID_%s_%s' #参数为(运营活动名, 活动表配置cfgID)
#设置运营活动ID的标记
Def_OperationActID = 'OperationActID_%s' #参数为运营活动名
#运营活动开启时世界等级,参数为运营活动名
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
index 42df784..e684816 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -34,6 +34,7 @@
import ChConfig
import GMCommon
import DirtyList
+import CrossBillboard
import PlayerBillboard
import PlayerExam
import PlayerControl
@@ -549,6 +550,10 @@
if callName == "UpdateBillboard": #地图服务器更新排行榜
PlayerBillboard.MapServer_UpdateBillboard(eval(resultName), tick)
return
+
+ if callName == "UpdateCrossBillboard": #地图服务器更新跨服排行榜
+ CrossBillboard.MapServer_UpdateCrossBillboard(eval(resultName))
+ return
if callName == 'PyAddFamilyInfoValue': #地图服务器增加战盟信息值
curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py b/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
index 5e225a8..7599174 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
@@ -14,7 +14,9 @@
import GameWorld
import PlayerSocial
+import CrossBillboard
import PlayerFamilyStore
+import PlayerCompensation
import PlayerBourse
import GameWorldBoss
import PlayerSealDemon
@@ -295,6 +297,8 @@
class PyGameDataManager(object):
def __init__(self):
+ self.CrossPersonalCompensationManager = PlayerCompensation.CrossPersonalCompensationManager()
+ self.CrossBillboardManager = CrossBillboard.CrossBillboardManager()
self.PlayerAssistThanksPyManager = PlayerAssistThanksPyManager()
self.PlayerAssistPyManager = PlayerAssistPyManager()
self.PlayerViewCachePyManager = PlayerViewCachePyManager()
@@ -318,6 +322,8 @@
def GetSaveData(self):
buff = ""
+ buff += self.CrossPersonalCompensationManager.GetSaveData()
+ buff += self.CrossBillboardManager.GetSaveData()
buff += self.PlayerAssistThanksPyManager.GetSaveData()
buff += self.PlayerAssistPyManager.GetSaveData()
buff += self.PlayerViewCachePyManager.GetSaveData()
@@ -340,6 +346,8 @@
return buff
def LoadGameData(self, gameBuffer, pos):
+ pos = self.CrossPersonalCompensationManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
+ pos = self.CrossBillboardManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
pos = self.PlayerAssistThanksPyManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
pos = self.PlayerAssistPyManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
pos = self.PlayerViewCachePyManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
@@ -369,6 +377,16 @@
PyGameData.g_pyGameDataManager = pyGameDataMgr
return pyGameDataMgr
+def GetCrossPersonalCompensationManager():
+ # 跨服个人补偿邮件管理
+ pyGameDataMgr = GetPyGameDataManager()
+ return pyGameDataMgr.CrossPersonalCompensationManager
+
+def GetCrossBillboardManager():
+ # 跨服排行榜管理
+ pyGameDataMgr = GetPyGameDataManager()
+ return pyGameDataMgr.CrossBillboardManager
+
def GetPlayerAssistThanksPyManager():
# 协助感谢表
pyGameDataMgr = GetPyGameDataManager()
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py b/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
index 3d93548..5e6afa0 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
@@ -91,6 +91,10 @@
g_crossZoneName = "" # 跨服分区名
+g_crossActInfoDict = None # 跨服运营活动信息 {actName:{actInfoDict}, ...}
+
+g_crossMailPlayerDict = {} # 有跨服邮件的玩家ID信息 {playerID:tick, ...}
+
g_crossPlayerViewCache = {} # 查看跨服玩家信息 {playerID:[cacheInfo, updTick], ...}
g_crossPKPlayerDict = {} # 跨服PK玩家字典 {playerID:PKPlayer, ...}
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py b/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
index e5a824c..bcb5cc3 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
@@ -15,6 +15,257 @@
from ctypes import (Structure, memset, memmove, sizeof, addressof, create_string_buffer, string_at)
import CommFunc
+# 跨服补偿个人领取表 #tagDBCrossPersonalCompensation
+class tagDBCrossPersonalCompensation(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ('PlayerID', ctypes.c_ulong),
+ ('GUID', ctypes.c_char * 40),
+ ('LimitTime', ctypes.c_char * 30),
+ ('TextLen', ctypes.c_ulong),
+ ('Text', ctypes.c_char_p),
+ ('Gold', ctypes.c_ulong),
+ ('GoldPaper', ctypes.c_ulong),
+ ('Silver', ctypes.c_ulong),
+ ('ItemLen', ctypes.c_ushort),
+ ('ItemInfo', ctypes.c_char_p),
+ ('DetailLen', ctypes.c_ushort),
+ ('Detail', ctypes.c_char_p),
+ ('MoneySource', ctypes.c_ushort),
+ ('ADOResult', ctypes.c_ulong),
+ ]
+
+ def __init__(self):
+ Structure.__init__(self)
+ self.clear()
+
+ def clear(self):
+ self.PlayerID = 0
+ self.GUID = ''
+ self.LimitTime = ''
+ self.TextLen = 0
+ self.Text = ''
+ self.Gold = 0
+ self.GoldPaper = 0
+ self.Silver = 0
+ self.ItemLen = 0
+ self.ItemInfo = ''
+ self.DetailLen = 0
+ self.Detail = ''
+ self.MoneySource = 0
+
+ def readData(self, buf, pos = 0, length = 0):
+ if not pos <= length:
+ return -1
+ if len(buf) < pos + self.getLength():
+ return -1
+ self.clear()
+ self.PlayerID, pos = CommFunc.ReadDWORD(buf, pos)
+ self.GUID, pos = CommFunc.ReadString(buf, pos, 40)
+ self.LimitTime, pos = CommFunc.ReadString(buf, pos, 30)
+ self.TextLen, pos = CommFunc.ReadDWORD(buf, pos)
+ tmp, pos = CommFunc.ReadString(buf, pos, self.TextLen)
+ self.Text = ctypes.c_char_p(tmp)
+ self.Gold, pos = CommFunc.ReadDWORD(buf, pos)
+ self.GoldPaper, pos = CommFunc.ReadDWORD(buf, pos)
+ self.Silver, pos = CommFunc.ReadDWORD(buf, pos)
+ self.ItemLen, pos = CommFunc.ReadWORD(buf, pos)
+ tmp, pos = CommFunc.ReadString(buf, pos, self.ItemLen)
+ self.ItemInfo = ctypes.c_char_p(tmp)
+ self.DetailLen, pos = CommFunc.ReadWORD(buf, pos)
+ tmp, pos = CommFunc.ReadString(buf, pos, self.DetailLen)
+ self.Detail = ctypes.c_char_p(tmp)
+ self.MoneySource, pos = CommFunc.ReadWORD(buf, pos)
+ return self.getLength()
+
+ def getBuffer(self):
+ buf = ''
+ buf = CommFunc.WriteDWORD(buf, self.PlayerID)
+ buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 40, self.GUID)
+ buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 30, self.LimitTime)
+ buf = CommFunc.WriteDWORD(buf, self.TextLen)
+ buf = CommFunc.WriteString(buf, self.TextLen, self.Text)
+ buf = CommFunc.WriteDWORD(buf, self.Gold)
+ buf = CommFunc.WriteDWORD(buf, self.GoldPaper)
+ buf = CommFunc.WriteDWORD(buf, self.Silver)
+ buf = CommFunc.WriteWORD(buf, self.ItemLen)
+ buf = CommFunc.WriteString(buf, self.ItemLen, self.ItemInfo)
+ buf = CommFunc.WriteWORD(buf, self.DetailLen)
+ buf = CommFunc.WriteString(buf, self.DetailLen, self.Detail)
+ buf = CommFunc.WriteWORD(buf, self.MoneySource)
+ return buf
+
+ def getLength(self):
+ length = 0
+ length += sizeof(ctypes.c_ulong)
+ length += sizeof(ctypes.c_char) * 40
+ length += sizeof(ctypes.c_char) * 30
+ length += sizeof(ctypes.c_ulong)
+ length += self.TextLen
+ length += sizeof(ctypes.c_ulong)
+ length += sizeof(ctypes.c_ulong)
+ length += sizeof(ctypes.c_ulong)
+ length += sizeof(ctypes.c_ushort)
+ length += self.ItemLen
+ length += sizeof(ctypes.c_ushort)
+ length += self.DetailLen
+ length += sizeof(ctypes.c_ushort)
+ return length
+
+ def outputString(self):
+ output = '''// 跨服补偿个人领取表 #tagDBCrossPersonalCompensation:
+ PlayerID = %s,
+ GUID = %s,
+ LimitTime = %s,
+ TextLen = %s,
+ Text = %s,
+ Gold = %s,
+ GoldPaper = %s,
+ Silver = %s,
+ ItemLen = %s,
+ ItemInfo = %s,
+ DetailLen = %s,
+ Detail = %s,
+ MoneySource = %s,
+ ADOResult = %s,
+ '''%(
+ self.PlayerID,
+ self.GUID,
+ self.LimitTime,
+ self.TextLen,
+ self.Text,
+ self.Gold,
+ self.GoldPaper,
+ self.Silver,
+ self.ItemLen,
+ self.ItemInfo,
+ self.DetailLen,
+ self.Detail,
+ self.MoneySource,
+ self.ADOResult,
+ )
+ return output
+
+ #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
+ def SetGUID(self,Str):
+ if len(Str)<=40:
+ self.GUID = Str
+ else:
+ self.GUID = Str[:40]
+
+ def SetLimitTime(self,Str):
+ if len(Str)<=30:
+ self.LimitTime = Str
+ else:
+ self.LimitTime = Str[:30]
+
+
+# 跨服排行榜 #tagDBCrossBillboard
+class tagDBCrossBillboard(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ('GroupValue1', ctypes.c_ubyte),
+ ('GroupValue2', ctypes.c_ubyte),
+ ('BillboardType', ctypes.c_ubyte),
+ ('ID', ctypes.c_ulong),
+ ('ID2', ctypes.c_ulong),
+ ('Name1', ctypes.c_char * 33),
+ ('Name2', ctypes.c_char * 33),
+ ('Type2', ctypes.c_ubyte),
+ ('Value1', ctypes.c_ulong),
+ ('Value2', ctypes.c_ulong),
+ ('CmpValue', ctypes.c_ulong),
+ ('CmpValue2', ctypes.c_ulong),
+ ('CmpValue3', ctypes.c_ulong),
+ ('ADOResult', ctypes.c_ulong),
+ ]
+
+ def __init__(self):
+ Structure.__init__(self)
+ self.clear()
+
+
+ def clear(self):
+ memset(addressof(self), 0, self.getLength())
+
+ def readData(self, buf, pos = 0, length = 0):
+ if not pos <= length:
+ return -1
+ if len(buf) < pos + self.getLength():
+ return -1
+ self.clear()
+ self.GroupValue1, pos = CommFunc.ReadBYTE(buf, pos)
+ self.GroupValue2, pos = CommFunc.ReadBYTE(buf, pos)
+ self.BillboardType, pos = CommFunc.ReadBYTE(buf, pos)
+ self.ID, pos = CommFunc.ReadDWORD(buf, pos)
+ self.ID2, pos = CommFunc.ReadDWORD(buf, pos)
+ self.Name1, pos = CommFunc.ReadString(buf, pos, 33)
+ self.Name2, pos = CommFunc.ReadString(buf, pos, 33)
+ self.Type2, pos = CommFunc.ReadBYTE(buf, pos)
+ self.Value1, pos = CommFunc.ReadDWORD(buf, pos)
+ self.Value2, pos = CommFunc.ReadDWORD(buf, pos)
+ self.CmpValue, pos = CommFunc.ReadDWORD(buf, pos)
+ self.CmpValue2, pos = CommFunc.ReadDWORD(buf, pos)
+ self.CmpValue3, pos = CommFunc.ReadDWORD(buf, pos)
+ return self.getLength()
+
+
+ def getBuffer(self):
+ buf = create_string_buffer(self.getLength())
+ memmove(addressof(buf), addressof(self), self.getLength())
+ return string_at(addressof(buf), self.getLength())
+
+ def getLength(self):
+ return sizeof(tagDBCrossBillboard)
+
+ def outputString(self):
+ output = '''// 跨服排行榜 #tagDBCrossBillboard:
+ GroupValue1 = %s,
+ GroupValue2 = %s,
+ BillboardType = %s,
+ ID = %s,
+ ID2 = %s,
+ Name1 = %s,
+ Name2 = %s,
+ Type2 = %s,
+ Value1 = %s,
+ Value2 = %s,
+ CmpValue = %s,
+ CmpValue2 = %s,
+ CmpValue3 = %s,
+ ADOResult = %s,
+ '''%(
+ self.GroupValue1,
+ self.GroupValue2,
+ self.BillboardType,
+ self.ID,
+ self.ID2,
+ self.Name1,
+ self.Name2,
+ self.Type2,
+ self.Value1,
+ self.Value2,
+ self.CmpValue,
+ self.CmpValue2,
+ self.CmpValue3,
+ self.ADOResult,
+ )
+ return output
+
+ #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
+ def SetName1(self,Str):
+ if len(Str)<=33:
+ self.Name1 = Str
+ else:
+ self.Name1 = Str[:33]
+
+ def SetName2(self,Str):
+ if len(Str)<=33:
+ self.Name2 = Str
+ else:
+ self.Name2 = Str[:33]
+
+
# 协助感谢表 #tagDBAssistThanks
class tagDBAssistThanks(Structure):
_pack_ = 1
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 734ef0f..1282455 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -3767,6 +3767,66 @@
#------------------------------------------------------
+# C0 04 查看跨服排行榜 #tagCGViewCrossBillboard
+
+class tagCGViewCrossBillboard(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("Type", c_ubyte), #榜单类型
+ ("GroupValue1", c_ubyte), # 分组值1
+ ("GroupValue2", c_ubyte), # 分组值2,与分组值1组合归为同组榜单数据
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC0
+ self.SubCmd = 0x04
+ return
+
+ def ReadData(self, stringData, _pos=0, _len=0):
+ self.Clear()
+ memmove(addressof(self), stringData[_pos:], self.GetLength())
+ return _pos + self.GetLength()
+
+ def Clear(self):
+ self.Cmd = 0xC0
+ self.SubCmd = 0x04
+ self.Type = 0
+ self.GroupValue1 = 0
+ self.GroupValue2 = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCGViewCrossBillboard)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 04 查看跨服排行榜 //tagCGViewCrossBillboard:
+ Cmd:%s,
+ SubCmd:%s,
+ Type:%d,
+ GroupValue1:%d,
+ GroupValue2:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.Type,
+ self.GroupValue1,
+ self.GroupValue2
+ )
+ return DumpString
+
+
+m_NAtagCGViewCrossBillboard=tagCGViewCrossBillboard()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGViewCrossBillboard.Cmd,m_NAtagCGViewCrossBillboard.SubCmd))] = m_NAtagCGViewCrossBillboard
+
+
+#------------------------------------------------------
# C0 01 查看跨服竞技场赛季排行榜 #tagCGViewCrossPKBillboard
class tagCGViewCrossPKBillboard(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 054a382..f873f17 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -5067,6 +5067,70 @@
#------------------------------------------------------
+# AC 12 跨服运营活动结束 # tagGCCrossActEnd
+
+class tagGCCrossActEnd(Structure):
+ Head = tagHead()
+ ActNameLen = 0 #(BYTE ActNameLen)
+ ActName = "" #(String ActName)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xAC
+ self.Head.SubCmd = 0x12
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.ActNameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ActName,_pos = CommFunc.ReadString(_lpData, _pos,self.ActNameLen)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xAC
+ self.Head.SubCmd = 0x12
+ self.ActNameLen = 0
+ self.ActName = ""
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += len(self.ActName)
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.ActNameLen)
+ data = CommFunc.WriteString(data, self.ActNameLen, self.ActName)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ ActNameLen:%d,
+ ActName:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.ActNameLen,
+ self.ActName
+ )
+ return DumpString
+
+
+m_NAtagGCCrossActEnd=tagGCCrossActEnd()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCCrossActEnd.Head.Cmd,m_NAtagGCCrossActEnd.Head.SubCmd))] = m_NAtagGCCrossActEnd
+
+
+#------------------------------------------------------
# AC 09 仙界盛典活动信息 #tagGCFairyCeremonyInfo
class tagGCFairyCeremonyInfo(Structure):
@@ -11037,6 +11101,190 @@
m_NAtagGCTeamMemFuncDataList=tagGCTeamMemFuncDataList()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCTeamMemFuncDataList.Head.Cmd,m_NAtagGCTeamMemFuncDataList.Head.SubCmd))] = m_NAtagGCTeamMemFuncDataList
+
+
+#------------------------------------------------------
+# C0 07 跨服排行榜信息 #tagGCCrossBillboardInfo
+
+class tagGCCrossBillboardData(Structure):
+ ID = 0 #(DWORD ID)
+ Name1 = "" #(char Name1[33])//名字1,用来显示排序对象名字
+ Name2 = "" #(char Name2[33])//名字2
+ Type2 = 0 #(BYTE Type2)//附加类型,用来表示排序对象的类型,比如,玩家所属职业门派,宠物类型等
+ Value1 = 0 #(DWORD Value1)//自定义值1
+ Value2 = 0 #(DWORD Value2)//自定义值2
+ CmpValue = 0 #(DWORD CmpValue)// 比较权值
+ CmpValue2 = 0 #(DWORD CmpValue2)// 比较权值
+ CmpValue3 = 0 #(DWORD CmpValue3)// 比较权值
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.ID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name1,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.Name2,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.Type2,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.Value1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Value2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.CmpValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.CmpValue2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.CmpValue3,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.ID = 0
+ self.Name1 = ""
+ self.Name2 = ""
+ self.Type2 = 0
+ self.Value1 = 0
+ self.Value2 = 0
+ self.CmpValue = 0
+ self.CmpValue2 = 0
+ self.CmpValue3 = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 33
+ length += 1
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.ID)
+ data = CommFunc.WriteString(data, 33, self.Name1)
+ data = CommFunc.WriteString(data, 33, self.Name2)
+ data = CommFunc.WriteBYTE(data, self.Type2)
+ data = CommFunc.WriteDWORD(data, self.Value1)
+ data = CommFunc.WriteDWORD(data, self.Value2)
+ data = CommFunc.WriteDWORD(data, self.CmpValue)
+ data = CommFunc.WriteDWORD(data, self.CmpValue2)
+ data = CommFunc.WriteDWORD(data, self.CmpValue3)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ ID:%d,
+ Name1:%s,
+ Name2:%s,
+ Type2:%d,
+ Value1:%d,
+ Value2:%d,
+ CmpValue:%d,
+ CmpValue2:%d,
+ CmpValue3:%d
+ '''\
+ %(
+ self.ID,
+ self.Name1,
+ self.Name2,
+ self.Type2,
+ self.Value1,
+ self.Value2,
+ self.CmpValue,
+ self.CmpValue2,
+ self.CmpValue3
+ )
+ return DumpString
+
+
+class tagGCCrossBillboardInfo(Structure):
+ Head = tagHead()
+ Type = 0 #(BYTE Type)//榜单类型
+ GroupValue1 = 0 #(BYTE GroupValue1)// 分组值1
+ GroupValue2 = 0 #(BYTE GroupValue2)// 分组值2,与分组值1组合归为同组榜单数据
+ BillboardCount = 0 #(BYTE BillboardCount)
+ CrossBillboardDataList = list() #(vector<tagGCCrossBillboardData> CrossBillboardDataList)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x07
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.Type,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupValue1,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupValue2,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.BillboardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.BillboardCount):
+ temCrossBillboardDataList = tagGCCrossBillboardData()
+ _pos = temCrossBillboardDataList.ReadData(_lpData, _pos)
+ self.CrossBillboardDataList.append(temCrossBillboardDataList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x07
+ self.Type = 0
+ self.GroupValue1 = 0
+ self.GroupValue2 = 0
+ self.BillboardCount = 0
+ self.CrossBillboardDataList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += 1
+ length += 1
+ length += 1
+ for i in range(self.BillboardCount):
+ length += self.CrossBillboardDataList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.Type)
+ data = CommFunc.WriteBYTE(data, self.GroupValue1)
+ data = CommFunc.WriteBYTE(data, self.GroupValue2)
+ data = CommFunc.WriteBYTE(data, self.BillboardCount)
+ for i in range(self.BillboardCount):
+ data = CommFunc.WriteString(data, self.CrossBillboardDataList[i].GetLength(), self.CrossBillboardDataList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ Type:%d,
+ GroupValue1:%d,
+ GroupValue2:%d,
+ BillboardCount:%d,
+ CrossBillboardDataList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.Type,
+ self.GroupValue1,
+ self.GroupValue2,
+ self.BillboardCount,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCCrossBillboardInfo=tagGCCrossBillboardInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCCrossBillboardInfo.Head.Cmd,m_NAtagGCCrossBillboardInfo.Head.SubCmd))] = m_NAtagGCCrossBillboardInfo
#------------------------------------------------------
@@ -25809,6 +26057,427 @@
#------------------------------------------------------
+# AA 32 跨服充值排行活动信息 #tagMCCACTGBillboardInfo
+
+class tagMCCACTGBillboardAwardItem(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("ItemID", c_int),
+ ("ItemCount", c_ushort),
+ ("IsBind", c_ubyte), # 是否拍品
+ ]
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, stringData, _pos=0, _len=0):
+ self.Clear()
+ memmove(addressof(self), stringData[_pos:], self.GetLength())
+ return _pos + self.GetLength()
+
+ def Clear(self):
+ self.ItemID = 0
+ self.ItemCount = 0
+ self.IsBind = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagMCCACTGBillboardAwardItem)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// AA 32 跨服充值排行活动信息 //tagMCCACTGBillboardInfo:
+ ItemID:%d,
+ ItemCount:%d,
+ IsBind:%d
+ '''\
+ %(
+ self.ItemID,
+ self.ItemCount,
+ self.IsBind
+ )
+ return DumpString
+
+
+class tagMCCACTGBillboardDabiao(Structure):
+ AwardIndex = 0 #(BYTE AwardIndex)// 奖励索引 0~31
+ NeedRMB = 0 #(DWORD NeedRMB)// 所需充值RMB
+ AwardItemCount = 0 #(BYTE AwardItemCount)// 奖励物品数
+ AwardItemList = list() #(vector<tagMCCACTGBillboardAwardItem> AwardItemList)// 奖励物品信息
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.AwardIndex,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.NeedRMB,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.AwardItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.AwardItemCount):
+ temAwardItemList = tagMCCACTGBillboardAwardItem()
+ _pos = temAwardItemList.ReadData(_lpData, _pos)
+ self.AwardItemList.append(temAwardItemList)
+ return _pos
+
+ def Clear(self):
+ self.AwardIndex = 0
+ self.NeedRMB = 0
+ self.AwardItemCount = 0
+ self.AwardItemList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 4
+ length += 1
+ for i in range(self.AwardItemCount):
+ length += self.AwardItemList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.AwardIndex)
+ data = CommFunc.WriteDWORD(data, self.NeedRMB)
+ data = CommFunc.WriteBYTE(data, self.AwardItemCount)
+ for i in range(self.AwardItemCount):
+ data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ AwardIndex:%d,
+ NeedRMB:%d,
+ AwardItemCount:%d,
+ AwardItemList:%s
+ '''\
+ %(
+ self.AwardIndex,
+ self.NeedRMB,
+ self.AwardItemCount,
+ "..."
+ )
+ return DumpString
+
+
+class tagMCCACTGBillboardOrder(Structure):
+ OrderA = 0 #(BYTE OrderA)// 名次A
+ OrderB = 0 #(BYTE OrderB)// 至名次B
+ NeedRMB = 0 #(DWORD NeedRMB)// 所需充值RMB,未达标的该名次空,排名后面的玩家向下顺延
+ AwardItemCount = 0 #(BYTE AwardItemCount)// 奖励物品数
+ AwardItemList = list() #(vector<tagMCCACTGBillboardAwardItem> AwardItemList)// 奖励物品信息
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.OrderA,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.OrderB,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.NeedRMB,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.AwardItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.AwardItemCount):
+ temAwardItemList = tagMCCACTGBillboardAwardItem()
+ _pos = temAwardItemList.ReadData(_lpData, _pos)
+ self.AwardItemList.append(temAwardItemList)
+ return _pos
+
+ def Clear(self):
+ self.OrderA = 0
+ self.OrderB = 0
+ self.NeedRMB = 0
+ self.AwardItemCount = 0
+ self.AwardItemList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 1
+ length += 4
+ length += 1
+ for i in range(self.AwardItemCount):
+ length += self.AwardItemList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.OrderA)
+ data = CommFunc.WriteBYTE(data, self.OrderB)
+ data = CommFunc.WriteDWORD(data, self.NeedRMB)
+ data = CommFunc.WriteBYTE(data, self.AwardItemCount)
+ for i in range(self.AwardItemCount):
+ data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ OrderA:%d,
+ OrderB:%d,
+ NeedRMB:%d,
+ AwardItemCount:%d,
+ AwardItemList:%s
+ '''\
+ %(
+ self.OrderA,
+ self.OrderB,
+ self.NeedRMB,
+ self.AwardItemCount,
+ "..."
+ )
+ return DumpString
+
+
+class tagMCCACTGBillboardTempInfo(Structure):
+ TemplateID = 0 #(BYTE TemplateID)// 活动模板ID
+ DabiaoAwardCount = 0 #(BYTE DabiaoAwardCount)// 达标奖励档数
+ DabiaoAwardInfo = list() #(vector<tagMCCACTGBillboardDabiao> DabiaoAwardInfo)// 达标奖励信息
+ OrderAwardCount = 0 #(BYTE OrderAwardCount)// 排行奖励档数
+ OrderAwardInfo = list() #(vector<tagMCCACTGBillboardOrder> OrderAwardInfo)// 排行奖励信息
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.TemplateID,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.DabiaoAwardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.DabiaoAwardCount):
+ temDabiaoAwardInfo = tagMCCACTGBillboardDabiao()
+ _pos = temDabiaoAwardInfo.ReadData(_lpData, _pos)
+ self.DabiaoAwardInfo.append(temDabiaoAwardInfo)
+ self.OrderAwardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.OrderAwardCount):
+ temOrderAwardInfo = tagMCCACTGBillboardOrder()
+ _pos = temOrderAwardInfo.ReadData(_lpData, _pos)
+ self.OrderAwardInfo.append(temOrderAwardInfo)
+ return _pos
+
+ def Clear(self):
+ self.TemplateID = 0
+ self.DabiaoAwardCount = 0
+ self.DabiaoAwardInfo = list()
+ self.OrderAwardCount = 0
+ self.OrderAwardInfo = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 1
+ for i in range(self.DabiaoAwardCount):
+ length += self.DabiaoAwardInfo[i].GetLength()
+ length += 1
+ for i in range(self.OrderAwardCount):
+ length += self.OrderAwardInfo[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.TemplateID)
+ data = CommFunc.WriteBYTE(data, self.DabiaoAwardCount)
+ for i in range(self.DabiaoAwardCount):
+ data = CommFunc.WriteString(data, self.DabiaoAwardInfo[i].GetLength(), self.DabiaoAwardInfo[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.OrderAwardCount)
+ for i in range(self.OrderAwardCount):
+ data = CommFunc.WriteString(data, self.OrderAwardInfo[i].GetLength(), self.OrderAwardInfo[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ TemplateID:%d,
+ DabiaoAwardCount:%d,
+ DabiaoAwardInfo:%s,
+ OrderAwardCount:%d,
+ OrderAwardInfo:%s
+ '''\
+ %(
+ self.TemplateID,
+ self.DabiaoAwardCount,
+ "...",
+ self.OrderAwardCount,
+ "..."
+ )
+ return DumpString
+
+
+class tagMCCACTGBillboardInfo(Structure):
+ Head = tagHead()
+ ServerInfoLen = 0 #(BYTE ServerInfoLen)
+ ServerIDRangeInfo = "" #(String ServerIDRangeInfo)//开放该活动的服务器ID范围列表,json格式 [[IDA, IDB], ...], [] 为全服
+ GroupValue1 = 0 #(BYTE GroupValue1)// 活动榜单分组值1,用于查询对应榜单
+ StartDate = "" #(char StartDate[10])// 开始日期 y-m-d
+ EndtDate = "" #(char EndtDate[10])// 结束日期 y-m-d
+ TemplateID = 0 #(BYTE TemplateID)// 当前活动模板ID
+ TemplateCount = 0 #(BYTE TemplateCount)
+ TempInfo = list() #(vector<tagMCCACTGBillboardTempInfo> TempInfo)// 模板信息
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xAA
+ self.Head.SubCmd = 0x32
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.ServerInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ServerIDRangeInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.ServerInfoLen)
+ self.GroupValue1,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+ self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+ self.TemplateID,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.TemplateCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.TemplateCount):
+ temTempInfo = tagMCCACTGBillboardTempInfo()
+ _pos = temTempInfo.ReadData(_lpData, _pos)
+ self.TempInfo.append(temTempInfo)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xAA
+ self.Head.SubCmd = 0x32
+ self.ServerInfoLen = 0
+ self.ServerIDRangeInfo = ""
+ self.GroupValue1 = 0
+ self.StartDate = ""
+ self.EndtDate = ""
+ self.TemplateID = 0
+ self.TemplateCount = 0
+ self.TempInfo = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += len(self.ServerIDRangeInfo)
+ length += 1
+ length += 10
+ length += 10
+ length += 1
+ length += 1
+ for i in range(self.TemplateCount):
+ length += self.TempInfo[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.ServerInfoLen)
+ data = CommFunc.WriteString(data, self.ServerInfoLen, self.ServerIDRangeInfo)
+ data = CommFunc.WriteBYTE(data, self.GroupValue1)
+ data = CommFunc.WriteString(data, 10, self.StartDate)
+ data = CommFunc.WriteString(data, 10, self.EndtDate)
+ data = CommFunc.WriteBYTE(data, self.TemplateID)
+ data = CommFunc.WriteBYTE(data, self.TemplateCount)
+ for i in range(self.TemplateCount):
+ data = CommFunc.WriteString(data, self.TempInfo[i].GetLength(), self.TempInfo[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ ServerInfoLen:%d,
+ ServerIDRangeInfo:%s,
+ GroupValue1:%d,
+ StartDate:%s,
+ EndtDate:%s,
+ TemplateID:%d,
+ TemplateCount:%d,
+ TempInfo:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.ServerInfoLen,
+ self.ServerIDRangeInfo,
+ self.GroupValue1,
+ self.StartDate,
+ self.EndtDate,
+ self.TemplateID,
+ self.TemplateCount,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagMCCACTGBillboardInfo=tagMCCACTGBillboardInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCCACTGBillboardInfo.Head.Cmd,m_NAtagMCCACTGBillboardInfo.Head.SubCmd))] = m_NAtagMCCACTGBillboardInfo
+
+
+#------------------------------------------------------
+# AA 33 跨服充值排行活动玩家信息 #tagMCCACTGBillboardPlayerInfo
+
+class tagMCCACTGBillboardPlayerInfo(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("CTGRMBTotal", c_int), # 活动已累计充值RMB
+ ("DabiaoAwardRecord", c_int), # 达标奖励记录,与达标奖励索引位或运算判断是否已领取
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xAA
+ self.SubCmd = 0x33
+ return
+
+ def ReadData(self, stringData, _pos=0, _len=0):
+ self.Clear()
+ memmove(addressof(self), stringData[_pos:], self.GetLength())
+ return _pos + self.GetLength()
+
+ def Clear(self):
+ self.Cmd = 0xAA
+ self.SubCmd = 0x33
+ self.CTGRMBTotal = 0
+ self.DabiaoAwardRecord = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagMCCACTGBillboardPlayerInfo)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// AA 33 跨服充值排行活动玩家信息 //tagMCCACTGBillboardPlayerInfo:
+ Cmd:%s,
+ SubCmd:%s,
+ CTGRMBTotal:%d,
+ DabiaoAwardRecord:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.CTGRMBTotal,
+ self.DabiaoAwardRecord
+ )
+ return DumpString
+
+
+m_NAtagMCCACTGBillboardPlayerInfo=tagMCCACTGBillboardPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCCACTGBillboardPlayerInfo.Cmd,m_NAtagMCCACTGBillboardPlayerInfo.SubCmd))] = m_NAtagMCCACTGBillboardPlayerInfo
+
+
+#------------------------------------------------------
# AA 09 消费返利活动信息 #tagMCCostRebateInfo
class tagMCCostRebateAwardItem(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 7bd3602..0d51728 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -1505,6 +1505,21 @@
("DWORD", "Weight", 0),
),
+ "CrossActCTGBillboardDabiao":(
+ ("DWORD", "TemplateID", 1),
+ ("DWORD", "CTGNeed", 0),
+ ("BYTE", "AwardIndex", 0),
+ ("list", "AwardItemList", 0),
+ ),
+
+ "CrossActCTGBillboardOrder":(
+ ("DWORD", "TemplateID", 1),
+ ("WORD", "OrderA", 0),
+ ("WORD", "OrderB", 0),
+ ("DWORD", "CTGAtleast", 0),
+ ("list", "AwardItemList", 0),
+ ),
+
"MysteryShop":(
("list", "LVRange", 0),
("DWORD", "GoodsID", 0),
@@ -4764,6 +4779,38 @@
def GetIsBind(self): return self.IsBind # 是否绑定
def GetWeight(self): return self.Weight # 权重
+# 跨服充值排行模板达标奖励表
+class IPY_CrossActCTGBillboardDabiao():
+
+ def __init__(self):
+ self.TemplateID = 0
+ self.CTGNeed = 0
+ self.AwardIndex = 0
+ self.AwardItemList = []
+ return
+
+ def GetTemplateID(self): return self.TemplateID # 模板ID
+ def GetCTGNeed(self): return self.CTGNeed # 需充值RMB
+ def GetAwardIndex(self): return self.AwardIndex # 奖励记录索引,从0开始,同个模板不可重复,不可变更
+ def GetAwardItemList(self): return self.AwardItemList # 奖励物品列表[[物品ID,个数,是否拍品], ...]
+
+# 跨服充值排行模板名次奖励表
+class IPY_CrossActCTGBillboardOrder():
+
+ def __init__(self):
+ self.TemplateID = 0
+ self.OrderA = 0
+ self.OrderB = 0
+ self.CTGAtleast = 0
+ self.AwardItemList = []
+ return
+
+ def GetTemplateID(self): return self.TemplateID # 模板ID
+ def GetOrderA(self): return self.OrderA # 名次A
+ def GetOrderB(self): return self.OrderB # 至名次B
+ def GetCTGAtleast(self): return self.CTGAtleast # 至少充值RMB
+ def GetAwardItemList(self): return self.AwardItemList # 奖励物品列表[[物品ID,个数,是否拍品], ...]
+
# 神秘商店表
class IPY_MysteryShop():
@@ -5430,6 +5477,10 @@
self.ipyActLuckyTreasureLen = len(self.ipyActLuckyTreasureCache)
self.ipyLuckyTreasureTemplateCache = self.__LoadFileData("LuckyTreasureTemplate", IPY_LuckyTreasureTemplate)
self.ipyLuckyTreasureTemplateLen = len(self.ipyLuckyTreasureTemplateCache)
+ self.ipyCrossActCTGBillboardDabiaoCache = self.__LoadFileData("CrossActCTGBillboardDabiao", IPY_CrossActCTGBillboardDabiao)
+ self.ipyCrossActCTGBillboardDabiaoLen = len(self.ipyCrossActCTGBillboardDabiaoCache)
+ self.ipyCrossActCTGBillboardOrderCache = self.__LoadFileData("CrossActCTGBillboardOrder", IPY_CrossActCTGBillboardOrder)
+ self.ipyCrossActCTGBillboardOrderLen = len(self.ipyCrossActCTGBillboardOrderCache)
self.ipyMysteryShopCache = self.__LoadFileData("MysteryShop", IPY_MysteryShop)
self.ipyMysteryShopLen = len(self.ipyMysteryShopCache)
self.ipyEquipPlaceIndexMapCache = self.__LoadFileData("EquipPlaceIndexMap", IPY_EquipPlaceIndexMap)
@@ -5932,6 +5983,10 @@
def GetActLuckyTreasureByIndex(self, index): return self.ipyActLuckyTreasureCache[index]
def GetLuckyTreasureTemplateCount(self): return self.ipyLuckyTreasureTemplateLen
def GetLuckyTreasureTemplateByIndex(self, index): return self.ipyLuckyTreasureTemplateCache[index]
+ def GetCrossActCTGBillboardDabiaoCount(self): return self.ipyCrossActCTGBillboardDabiaoLen
+ def GetCrossActCTGBillboardDabiaoByIndex(self, index): return self.ipyCrossActCTGBillboardDabiaoCache[index]
+ def GetCrossActCTGBillboardOrderCount(self): return self.ipyCrossActCTGBillboardOrderLen
+ def GetCrossActCTGBillboardOrderByIndex(self, index): return self.ipyCrossActCTGBillboardOrderCache[index]
def GetMysteryShopCount(self): return self.ipyMysteryShopLen
def GetMysteryShopByIndex(self, index): return self.ipyMysteryShopCache[index]
def GetEquipPlaceIndexMapCount(self): return self.ipyEquipPlaceIndexMapLen
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 9f49826..a62af50 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -110,6 +110,7 @@
import PlayerFeastRedPacket
import PlayerLuckyTreasure
import Item_ResetAttrPoint
+import CrossActCTGBillboard
import CrossRealmPlayer
import ChNetSendPack
import FamilyRobBoss
@@ -638,6 +639,8 @@
#通知基础属性
NotifyPlayerBasePoint(curPlayer)
+ #跨服充值排行
+ CrossActCTGBillboard.OnPlayerLogin(curPlayer)
#消费返利
PlayerCostRebate.OnPlayerLogin(curPlayer)
#累计充值
@@ -5398,6 +5401,9 @@
# 领取节日巡礼积分奖励
elif rewardType == ChConfig.Def_RewardType_FeastWeekPartyPoint:
PlayerFeastWeekParty.GetFeastWeekPartyPointAward(curPlayer, dataEx, dataExStr)
+ # 领取跨服充值排行活动达标奖励
+ elif rewardType == ChConfig.Def_RewardType_CACTGBillboardDabiao:
+ CrossActCTGBillboard.GetDabiaoAward(curPlayer, dataEx)
#缥缈奇遇领取
elif rewardType == ChConfig.Def_RewardType_FairyAdventuresAward:
PlayerFairyDomain.GetFairyAdventuresAward(curPlayer, dataEx, dataExStr)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossActCTGBillboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossActCTGBillboard.py
new file mode 100644
index 0000000..965bf5c
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossActCTGBillboard.py
@@ -0,0 +1,288 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.CrossActCTGBillboard
+#
+# @todo:跨服运营活动 - 充值排行
+# @author hxp
+# @date 2020-01-13
+# @version 1.0
+#
+# 详细描述: 跨服运营活动 - 充值排行
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2020-01-13 17:00"""
+#-------------------------------------------------------------------------------
+
+import ChConfig
+import ShareDefine
+import PlayerControl
+import NetPackCommon
+import PlayerBillboard
+import CrossRealmPlayer
+import ChPyNetSendPack
+import ItemControler
+import IPY_GameWorld
+import IpyGameDataPY
+import GameWorld
+
+def OnPlayerLogin(curPlayer):
+ isReset = __CheckPlayerCrossActCTGBillboard(curPlayer)
+ if not isReset:
+ actInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_CTGBillboard)
+ # 活动中同步活动信息
+ if actInfo.get(ShareDefine.ActKey_State):
+ Sync_CrossActCTGBillboardInfo(curPlayer)
+ Sync_CrossActCTGBillboardPlayerInfo(curPlayer)
+ UpdateCTGRMBCrossBillboard(curPlayer, actInfo)
+ return
+
+def RefreshCrossActCTGBillboardInfo():
+ ## 收到GameServer同步的活动信息,刷新活动信息
+ playerManager = GameWorld.GetPlayerManager()
+ for index in xrange(playerManager.GetPlayerCount()):
+ curPlayer = playerManager.GetPlayerByIndex(index)
+ if curPlayer.GetID() == 0:
+ continue
+ __CheckPlayerCrossActCTGBillboard(curPlayer)
+ return
+
+def __CheckPlayerCrossActCTGBillboard(curPlayer):
+ ## 检查玩家累计充值活动数据信息
+
+ playerID = curPlayer.GetPlayerID()
+
+ actInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_CTGBillboard)
+ cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
+ actID = actInfo.get(ShareDefine.ActKey_ID, 0)
+ state = actInfo.get(ShareDefine.ActKey_State, 0)
+ dayIndex = actInfo.get(ShareDefine.ActKey_DayIndex, 0)
+ templateID = actInfo.get(ShareDefine.ActKey_TemplateID, 0)
+
+ playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardID) # 玩家身上的活动ID
+ playerTemplateID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardTemplateID)
+
+ # 活动ID 相同的话不处理
+ if actID == playerActID:
+ GameWorld.DebugLog("跨服充值排行活动ID不变,不处理!cfgID=%s,dayIndex=%s,templateID=%s" % (cfgID, dayIndex, templateID), playerID)
+ if state:
+ if playerTemplateID != templateID and templateID:
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_CTGBillboardTemplateID, templateID)
+ GameWorld.DebugLog(" 活动模板ID变更,更新玩家身上模板ID记录!playerTemplateID=%s,updTemplateID=%s"
+ % (playerTemplateID, templateID), playerID)
+ Sync_CrossActCTGBillboardInfo(curPlayer)
+
+ return
+
+ GameWorld.DebugLog("跨服充值排行活动重置! cfgID=%s,actID=%s,playerActID=%s,state=%s" % (cfgID, actID, playerActID, state), playerID)
+
+ if not state:
+ CrossRealmPlayer.NotifyCrossActEnd(curPlayer, ShareDefine.CrossActName_CTGBillboard)
+
+ if playerActID and playerTemplateID:
+ __SendDabiaoAwardMail(curPlayer, playerTemplateID)
+
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_CTGBillboardID, actID)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_CTGBillboardTemplateID, templateID)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_CTGBillboardRMB, 0)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_CTGBillboardAward, 0)
+
+ Sync_CrossActCTGBillboardInfo(curPlayer)
+ Sync_CrossActCTGBillboardPlayerInfo(curPlayer)
+ return True
+
+def __SendDabiaoAwardMail(curPlayer, playerTemplateID):
+ ## 补发未领取的达标奖励
+
+ totalRMB = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardRMB)
+ if not totalRMB:
+ return
+
+ ipyDataList = IpyGameDataPY.GetIpyGameDataList("CrossActCTGBillboardDabiao", playerTemplateID)
+ if not ipyDataList:
+ return
+
+ playerID = curPlayer.GetPlayerID()
+ awardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardAward)
+ batchPlayerIDList, batchAddItemList, batchParamList = [], [], []
+ for ipyData in ipyDataList:
+ ctgNeed = ipyData.GetCTGNeed()
+ awardIndex = ipyData.GetAwardIndex()
+ if totalRMB < ctgNeed:
+ continue
+ if awardRecord & pow(2, awardIndex):
+ continue
+ batchPlayerIDList.append([playerID])
+ batchAddItemList.append(ipyData.GetAwardItemList())
+ batchParamList.append([ctgNeed])
+ awardRecord = awardRecord | pow(2, awardIndex)
+
+ if not batchPlayerIDList:
+ return
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_CTGBillboardAward, awardRecord)
+
+ GameWorld.DebugLog("补发跨服充值排行活动未领取达标奖励!", playerID)
+ PlayerControl.SendMailBatch("CACTGBillboardDabiao", batchPlayerIDList, batchAddItemList, batchParamList)
+ return
+
+def GetDabiaoAward(curPlayer, awardIndex):
+ ## 手动领取达标奖励
+
+ actInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_CTGBillboard)
+ state = actInfo.get(ShareDefine.ActKey_State, 0)
+ if not state:
+ GameWorld.DebugLog("非活动中")
+ return
+
+ totalRMB = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardRMB)
+ awardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardAward)
+ if awardRecord & pow(2, awardIndex):
+ GameWorld.DebugLog("已领取过该奖励! awardIndex=%s" % awardIndex)
+ return
+
+ playerTemplateID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardTemplateID)
+ ipyDataList = IpyGameDataPY.GetIpyGameDataList("CrossActCTGBillboardDabiao", playerTemplateID)
+ if not ipyDataList:
+ return
+
+ awardItemList = []
+ for ipyData in ipyDataList:
+ ctgNeed = ipyData.GetCTGNeed()
+ if awardIndex == ipyData.GetAwardIndex():
+ if totalRMB < ctgNeed:
+ GameWorld.DebugLog("充值额度未达标,无法领取! awardIndex=%s,totalRMB=%s,ctgNeed=%s"
+ % (awardIndex, totalRMB, ctgNeed))
+ return
+ awardItemList = ipyData.GetAwardItemList()
+ break
+
+ GameWorld.DebugLog("领取跨服充值活动达标奖励!awardIndex=%s,awardItemList=%s" % (awardIndex, awardItemList))
+ if not awardItemList:
+ return
+
+ if not ItemControler.CheckPackSpaceEnough(curPlayer, awardItemList):
+ return
+
+ updAwardRecord = awardRecord | pow(2, awardIndex)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_CTGBillboardAward, updAwardRecord)
+ Sync_CrossActCTGBillboardPlayerInfo(curPlayer)
+
+ for itemID, itemCount, isAuctionItem in awardItemList:
+ ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem],
+ event=["CrossActCTGBillboard", False, {}])
+
+ return
+
+def AddCTGRMB(curPlayer, addRMB):
+ ## 增加活动已累计充值RMB
+ actInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_CTGBillboard)
+ if not actInfo:
+ return
+
+ if not actInfo.get(ShareDefine.ActKey_State):
+ GameWorld.DebugLog("玩家区服ID跨服充值排行非活动中!playerServerID=%s" % GameWorld.GetPlayerServerID(curPlayer))
+ return
+
+ totalRMB = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardRMB) + addRMB
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_CTGBillboardRMB, totalRMB)
+
+ GameWorld.DebugLog("跨服充值排行活动增加玩家累计充值RMB: addRMB=%s,totalRMB=%s" % (addRMB, totalRMB), curPlayer.GetPlayerID())
+ Sync_CrossActCTGBillboardPlayerInfo(curPlayer)
+ UpdateCTGRMBCrossBillboard(curPlayer, actInfo)
+ return
+
+def UpdateCTGRMBCrossBillboard(curPlayer, actInfo):
+ ## 更新跨服充值活动榜
+ totalRMB = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardRMB)
+ if not totalRMB:
+ return
+ cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
+ if not cfgID:
+ return
+ cmpValue = totalRMB
+ PlayerBillboard.UpdatePlayerCrossBillboard(curPlayer, ShareDefine.Def_CBT_ActCTG, cfgID, cmpValue)
+ return
+
+def Sync_CrossActCTGBillboardPlayerInfo(curPlayer):
+ ## 通知活动玩家数据信息
+ playerActInfo = ChPyNetSendPack.tagMCCACTGBillboardPlayerInfo()
+ playerActInfo.CTGRMBTotal = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardRMB)
+ playerActInfo.DabiaoAwardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_CTGBillboardAward)
+ NetPackCommon.SendFakePack(curPlayer, playerActInfo)
+ return
+
+def Sync_CrossActCTGBillboardInfo(curPlayer):
+ ## 通知活动信息
+
+ actInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_CTGBillboard)
+ if not actInfo:
+ return
+
+ if not actInfo.get(ShareDefine.ActKey_State):
+ return
+
+ ipyDataDict = actInfo.get(ShareDefine.ActKey_IpyDataInfo, {})
+ if not ipyDataDict:
+ return 0
+
+ templateIDList = ipyDataDict.get("TemplateIDList", [])
+ if not templateIDList:
+ return
+
+ actPack = ChPyNetSendPack.tagMCCACTGBillboardInfo()
+ actPack.ServerIDRangeInfo = str(actInfo.get(ShareDefine.ActKey_ServerIDRangeList, []))
+ actPack.ServerInfoLen = len(actPack.ServerIDRangeInfo)
+ actPack.GroupValue1 = actInfo.get(ShareDefine.ActKey_CfgID, 0)
+ actPack.StartDate = ipyDataDict.get("StartDate", "")
+ actPack.EndtDate = ipyDataDict.get("EndDate", "")
+ actPack.TemplateID = actInfo.get(ShareDefine.ActKey_TemplateID, 0)
+ actPack.TempInfo = []
+ for templateID in templateIDList:
+ tempInfo = ChPyNetSendPack.tagMCCACTGBillboardTempInfo()
+
+ # 达标
+ tempInfo.TemplateID = templateID
+ tempInfo.DabiaoAwardInfo = []
+ dabiaoIpyDataList = IpyGameDataPY.GetIpyGameDataList("CrossActCTGBillboardDabiao", templateID)
+ if dabiaoIpyDataList:
+ for dabiaoIpyData in dabiaoIpyDataList:
+ dabiaoInfo = ChPyNetSendPack.tagMCCACTGBillboardDabiao()
+ dabiaoInfo.NeedRMB = dabiaoIpyData.GetCTGNeed()
+ dabiaoInfo.AwardIndex = dabiaoIpyData.GetAwardIndex()
+ dabiaoInfo.AwardItemList = []
+ for itemID, itemCount, isBind in dabiaoIpyData.GetAwardItemList():
+ itemInfo = ChPyNetSendPack.tagMCCACTGBillboardAwardItem()
+ itemInfo.ItemID = itemID
+ itemInfo.ItemCount = itemCount
+ itemInfo.IsBind = isBind
+ dabiaoInfo.AwardItemList.append(itemInfo)
+ dabiaoInfo.AwardItemCount = len(dabiaoInfo.AwardItemList)
+ tempInfo.DabiaoAwardInfo.append(dabiaoInfo)
+ tempInfo.DabiaoAwardCount = len(tempInfo.DabiaoAwardInfo)
+
+ # 排行
+ tempInfo.OrderAwardInfo = []
+ orderIpyDataList = IpyGameDataPY.GetIpyGameDataList("CrossActCTGBillboardOrder", templateID)
+ if orderIpyDataList:
+ for orderIpyData in orderIpyDataList:
+ orderInfo = ChPyNetSendPack.tagMCCACTGBillboardOrder()
+ orderInfo.OrderA = orderIpyData.GetOrderA()
+ orderInfo.OrderB = orderIpyData.GetOrderB()
+ orderInfo.NeedRMB = orderIpyData.GetCTGAtleast()
+ orderInfo.AwardItemList = []
+ for itemID, itemCount, isBind in orderIpyData.GetAwardItemList():
+ itemInfo = ChPyNetSendPack.tagMCCACTGBillboardAwardItem()
+ itemInfo.ItemID = itemID
+ itemInfo.ItemCount = itemCount
+ itemInfo.IsBind = isBind
+ orderInfo.AwardItemList.append(itemInfo)
+ orderInfo.AwardItemCount = len(orderInfo.AwardItemList)
+ tempInfo.OrderAwardInfo.append(orderInfo)
+ tempInfo.OrderAwardCount = len(tempInfo.OrderAwardInfo)
+
+ actPack.TempInfo.append(tempInfo)
+
+ actPack.TemplateCount = len(actPack.TempInfo)
+ NetPackCommon.SendFakePack(curPlayer, actPack)
+ return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
index 8eca865..ca42a7b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
@@ -15,10 +15,13 @@
#"""Version = 2018-12-21 18:00"""
#-------------------------------------------------------------------------------
import GameWorld
+import PyGameData
import ReadChConfig
import PlayerControl
import IpyGameDataPY
import IPY_GameWorld
+import ChPyNetSendPack
+import NetPackCommon
import ShareDefine
import ChConfig
import FBLogic
@@ -157,3 +160,37 @@
if PlayerControl.GetCrossMapID(curPlayer):
PlayerControl.SetCrossMapID(curPlayer, 0)
return
+
+def GetPlayerCrossActInfo(curPlayer, actName):
+ ## 获取跨服玩家对应的跨服活动信息
+ actInfoDict = PyGameData.g_crossActInfoDict.get(actName, {})
+ if not actInfoDict:
+ return {}
+ playerServerID = GameWorld.GetPlayerServerID(curPlayer)
+ for actInfo in actInfoDict.values():
+ if ShareDefine.ActKey_ServerIDRangeList not in actInfo:
+ continue
+ serverIDRangeList = actInfo[ShareDefine.ActKey_ServerIDRangeList]
+ if not serverIDRangeList:
+ # 全服开启
+ return actInfo
+ for serverIDA, serverIDB in serverIDRangeList:
+ if serverIDA <= playerServerID <= serverIDB:
+ return actInfo
+ return {}
+
+def NotifyCrossActEnd(curPlayer, actName):
+ '''通知跨服运营活动结束
+ 防止跨服服务器与子服时间不一致导致可能出现活动实际已关闭
+ 但是前端根据本服服务器时间判断还未关闭,可能引起玩家误以为活动未关闭而引发的一系列问题
+ 前端跨服活动显隐规则:
+ 显示:根据通知的活动包 且 时间>=活动开始日期 才显示
+ 关闭:收到后端通知的活动结束包 或 时间>=活动结束日期 则直接关闭活动界面
+ '''
+
+ clientPack = ChPyNetSendPack.tagGCCrossActEnd()
+ clientPack.ActName = actName
+ clientPack.ActNameLen = len(clientPack.ActName)
+ NetPackCommon.SendFakePack(curPlayer, clientPack)
+ return
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
index a03c9d4..860f197 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
@@ -20,6 +20,7 @@
import ChConfig
import PlayerControl
import OpenServerCampaign
+import CrossRealmPlayer
import GameFuncComm
import EventReport
@@ -86,7 +87,38 @@
sendMsg = "%s" % ({"Type":bType, "Type2":bType2, "ID":bID, "ID2":bID2, "Name1":bName, "Name2":bName2, "ExInfo":exInfo,
"Value1":value1, "Value2":value2, "CmpValue":cmpValue, "CmpValue2":cmpValue2, "CmpValue3":cmpValue3})
GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "UpdateBillboard", sendMsg, len(sendMsg))
- GameWorld.DebugLog("同步GameServer排行榜:bType=%s,%s" % (bType, sendMsg))
+ GameWorld.DebugLog("同步GameServer排行榜:bType=%s,cmpValue=%s, %s" % (bType, cmpValue, sendMsg), bID)
+ return
+
+def UpdatePlayerCrossBillboard(curPlayer, bType, groupValue1, cmpValue, cmpValue2=0, cmpValue3=0, value1=0, value2=0,
+ groupValue2=0):
+ ## 更新玩家跨服排行榜
+
+ #if not cmpValue and not cmpValue2 and not cmpValue3:
+ # return
+
+ #if not __CanPlayerBillboardComm(curPlayer):
+ # return
+
+ playerJob = GetBillboardJob(curPlayer)
+ playerID = curPlayer.GetID()
+ playerName = CrossRealmPlayer.GetCrossPlayerName(curPlayer)
+ playerOpInfo = GetBillboardOperateInfo(curPlayer)
+ if bType in ShareDefine.BTValue1_OfficialRankList:
+ value1 = curPlayer.GetOfficialRank()
+ id2 = 0
+ GameServer_UpdateCrossBillboard(bType, groupValue1, playerID, playerName, playerOpInfo, playerJob, value1, value2,
+ cmpValue, cmpValue2, cmpValue3, groupValue2, id2)
+ return
+
+def GameServer_UpdateCrossBillboard(bType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,
+ cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0):
+ sendMsg = "%s" % ({"Type":bType, "GroupValue1":groupValue1, "Type2":type2, "ID":dataID, "ID2":id2, "Name1":name1, "Name2":name2,
+ "Value1":value1, "Value2":value2, "CmpValue":cmpValue, "CmpValue2":cmpValue2, "CmpValue3":cmpValue3,
+ "GroupValue2":groupValue2})
+ GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "UpdateCrossBillboard", sendMsg, len(sendMsg))
+ GameWorld.DebugLog("同步GameServer跨服排行榜:bType=%s,groupValue1=%s,groupValue2=%s,cmpValue=%s, %s"
+ % (bType, groupValue1, groupValue2, cmpValue, sendMsg), dataID)
return
def UpdatePlayerFPTotalBillboard(curPlayer, isForceUpdate=False, isCheckRule=True):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
index 1eb4e41..b011cfd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -68,7 +68,8 @@
g_bzzdRefreshNPCListDict = {} # 仙界秘境所需击杀的NPC队列 {lineID:[npcID, npcID, ...], ...}
-g_operationActionDict = {} # {actName:actInfo, ...}
+g_operationActionDict = {} # 本服运营活动信息 {actName:actInfo, ...}
+g_crossActInfoDict = {} # 跨服运营活动信息 {actName:actInfo, ...}
g_npcKillerInfo = {} # NPC击杀者信息 {(lineID, objID, npcID):[killerDict, curTeam, hurtType, hurtID], ...}
--
Gitblit v1.8.0