hxp
2025-05-16 a7e72a169ff9fbd6d9d061f7352a130b8d53f9a6
16 卡牌服务端(排行榜)
13个文件已修改
2个文件已添加
1735 ■■■■ 已修改文件
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBDataMgr.py 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBBillboard.py 453 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py 478 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTruck.py 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -46,6 +46,18 @@
PacketSubCMD_1=0x37
PacketCallFunc_1=OnRequestMail
;排行榜
[PlayerBillboard]
ScriptName = Player\PlayerBillboard.py
Writer = hxp
Releaser = hxp
RegType = 0
RegisterPackCount = 1
PacketCMD_1=0xA1
PacketSubCMD_1=0x30
PacketCallFunc_1=OnViewBillboard
;法器
[PlayerFaQi]
ScriptName = Player\PlayerFaQi.py
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -6229,6 +6229,78 @@
#------------------------------------------------------
# A1 30 查看榜单 #tagCMViewBillboard
class  tagCMViewBillboard(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("Type", c_ubyte),    #榜单类型
                  ("GroupValue1", c_int),    #分组值1
                  ("GroupValue2", c_int),    #分组值2,与分组值1组合归为同组榜单数据
                  ("StartIndex", c_ushort),    #查看的起始名次索引, 默认0
                  ("ViewCnt", c_ubyte),    #查看条数,默认20,单次最大不超过100
                  ("ViewID", c_int),    #附带查看指定ID所在名次前后数据,如玩家ID、家族ID等,仅首页查询时有效,即StartIndex为0时
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA1
        self.SubCmd = 0x30
        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 = 0xA1
        self.SubCmd = 0x30
        self.Type = 0
        self.GroupValue1 = 0
        self.GroupValue2 = 0
        self.StartIndex = 0
        self.ViewCnt = 0
        self.ViewID = 0
        return
    def GetLength(self):
        return sizeof(tagCMViewBillboard)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A1 30 查看榜单 //tagCMViewBillboard:
                                Cmd:%s,
                                SubCmd:%s,
                                Type:%d,
                                GroupValue1:%d,
                                GroupValue2:%d,
                                StartIndex:%d,
                                ViewCnt:%d,
                                ViewID:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.Type,
                                self.GroupValue1,
                                self.GroupValue2,
                                self.StartIndex,
                                self.ViewCnt,
                                self.ViewID
                                )
        return DumpString
m_NAtagCMViewBillboard=tagCMViewBillboard()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMViewBillboard.Cmd,m_NAtagCMViewBillboard.SubCmd))] = m_NAtagCMViewBillboard
#------------------------------------------------------
# A2 19 游戏建议收集 #tagCMAdviceSubmit
class  tagCMAdviceSubmit(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -22784,6 +22784,300 @@
#------------------------------------------------------
# A1 30 查看榜单返回信息 #tagMCViewBillboardRet
class  tagMCViewBillboardData(Structure):
    Index = 0    #(WORD Index)//数据在榜单列表中的索引,从0开始
    Rank = 0    #(WORD Rank)//名次,从1开始,代表第1名
    ID = 0    #(DWORD ID)
    ID2 = 0    #(DWORD ID2)
    Name1 = ""    #(char Name1[33])//名字1,用来显示排序对象名字
    Name2 = ""    #(char Name2[65])//名字2
    Type2 = 0    #(BYTE Type2)//附加类型,用来表示排序对象的类型,比如,玩家所属职业门派,宠物类型等
    Value1 = 0    #(DWORD Value1)//自定义值1
    Value2 = 0    #(DWORD Value2)//自定义值2
    Value3 = 0    #(DWORD Value3)
    Value4 = 0    #(DWORD Value4)
    Value5 = 0    #(DWORD Value5)
    Value6 = 0    #(DWORD Value6)
    Value7 = 0    #(DWORD Value7)
    Value8 = 0    #(DWORD Value8)
    CmpValue = 0    #(DWORD CmpValue)// 比较权值
    CmpValue2 = 0    #(DWORD CmpValue2)// 比较权值
    CmpValue3 = 0    #(DWORD CmpValue3)// 比较权值
    DataLen = 0    #(WORD DataLen)
    UserData = ""    #(String UserData)//附加信息
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.Index,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.Rank,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.ID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.ID2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Name1,_pos = CommFunc.ReadString(_lpData, _pos,33)
        self.Name2,_pos = CommFunc.ReadString(_lpData, _pos,65)
        self.Type2,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.Value1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Value2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Value3,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Value4,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Value5,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Value6,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Value7,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Value8,_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)
        self.DataLen,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.UserData,_pos = CommFunc.ReadString(_lpData, _pos,self.DataLen)
        return _pos
    def Clear(self):
        self.Index = 0
        self.Rank = 0
        self.ID = 0
        self.ID2 = 0
        self.Name1 = ""
        self.Name2 = ""
        self.Type2 = 0
        self.Value1 = 0
        self.Value2 = 0
        self.Value3 = 0
        self.Value4 = 0
        self.Value5 = 0
        self.Value6 = 0
        self.Value7 = 0
        self.Value8 = 0
        self.CmpValue = 0
        self.CmpValue2 = 0
        self.CmpValue3 = 0
        self.DataLen = 0
        self.UserData = ""
        return
    def GetLength(self):
        length = 0
        length += 2
        length += 2
        length += 4
        length += 4
        length += 33
        length += 65
        length += 1
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 2
        length += len(self.UserData)
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteWORD(data, self.Index)
        data = CommFunc.WriteWORD(data, self.Rank)
        data = CommFunc.WriteDWORD(data, self.ID)
        data = CommFunc.WriteDWORD(data, self.ID2)
        data = CommFunc.WriteString(data, 33, self.Name1)
        data = CommFunc.WriteString(data, 65, 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.Value3)
        data = CommFunc.WriteDWORD(data, self.Value4)
        data = CommFunc.WriteDWORD(data, self.Value5)
        data = CommFunc.WriteDWORD(data, self.Value6)
        data = CommFunc.WriteDWORD(data, self.Value7)
        data = CommFunc.WriteDWORD(data, self.Value8)
        data = CommFunc.WriteDWORD(data, self.CmpValue)
        data = CommFunc.WriteDWORD(data, self.CmpValue2)
        data = CommFunc.WriteDWORD(data, self.CmpValue3)
        data = CommFunc.WriteWORD(data, self.DataLen)
        data = CommFunc.WriteString(data, self.DataLen, self.UserData)
        return data
    def OutputString(self):
        DumpString = '''
                                Index:%d,
                                Rank:%d,
                                ID:%d,
                                ID2:%d,
                                Name1:%s,
                                Name2:%s,
                                Type2:%d,
                                Value1:%d,
                                Value2:%d,
                                Value3:%d,
                                Value4:%d,
                                Value5:%d,
                                Value6:%d,
                                Value7:%d,
                                Value8:%d,
                                CmpValue:%d,
                                CmpValue2:%d,
                                CmpValue3:%d,
                                DataLen:%d,
                                UserData:%s
                                '''\
                                %(
                                self.Index,
                                self.Rank,
                                self.ID,
                                self.ID2,
                                self.Name1,
                                self.Name2,
                                self.Type2,
                                self.Value1,
                                self.Value2,
                                self.Value3,
                                self.Value4,
                                self.Value5,
                                self.Value6,
                                self.Value7,
                                self.Value8,
                                self.CmpValue,
                                self.CmpValue2,
                                self.CmpValue3,
                                self.DataLen,
                                self.UserData
                                )
        return DumpString
class  tagMCViewBillboardRet(Structure):
    Head = tagHead()
    Type = 0    #(BYTE Type)//榜单类型
    GroupValue1 = 0    #(DWORD GroupValue1)//分组值1
    GroupValue2 = 0    #(DWORD GroupValue2)//分组值2,与分组值1组合归为同组榜单数据
    DataTotal = 0    #(WORD DataTotal)//该榜单实际总数据数,分页查询时可通过此值及返回的分页最后一条榜单数据所在索引判断是否还有未查询数据
    PageDataCnt = 0    #(BYTE PageDataCnt)
    PageDataList = list()    #(vector<tagMCViewBillboardData> PageDataList)//返回分页数据列表
    ViewID = 0    #(DWORD ViewID)//附带查看指定ID所在名次前后数据,如玩家ID、家族ID等
    ViewIDDataCnt = 0    #(BYTE ViewIDDataCnt)
    ViewIDDataList = list()    #(vector<tagMCViewBillboardData> ViewIDDataList)//ViewID所在名次前后数据列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA1
        self.Head.SubCmd = 0x30
        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.ReadDWORD(_lpData, _pos)
        self.GroupValue2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.DataTotal,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.PageDataCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.PageDataCnt):
            temPageDataList = tagMCViewBillboardData()
            _pos = temPageDataList.ReadData(_lpData, _pos)
            self.PageDataList.append(temPageDataList)
        self.ViewID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.ViewIDDataCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.ViewIDDataCnt):
            temViewIDDataList = tagMCViewBillboardData()
            _pos = temViewIDDataList.ReadData(_lpData, _pos)
            self.ViewIDDataList.append(temViewIDDataList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA1
        self.Head.SubCmd = 0x30
        self.Type = 0
        self.GroupValue1 = 0
        self.GroupValue2 = 0
        self.DataTotal = 0
        self.PageDataCnt = 0
        self.PageDataList = list()
        self.ViewID = 0
        self.ViewIDDataCnt = 0
        self.ViewIDDataList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 4
        length += 4
        length += 2
        length += 1
        for i in range(self.PageDataCnt):
            length += self.PageDataList[i].GetLength()
        length += 4
        length += 1
        for i in range(self.ViewIDDataCnt):
            length += self.ViewIDDataList[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.WriteDWORD(data, self.GroupValue1)
        data = CommFunc.WriteDWORD(data, self.GroupValue2)
        data = CommFunc.WriteWORD(data, self.DataTotal)
        data = CommFunc.WriteBYTE(data, self.PageDataCnt)
        for i in range(self.PageDataCnt):
            data = CommFunc.WriteString(data, self.PageDataList[i].GetLength(), self.PageDataList[i].GetBuffer())
        data = CommFunc.WriteDWORD(data, self.ViewID)
        data = CommFunc.WriteBYTE(data, self.ViewIDDataCnt)
        for i in range(self.ViewIDDataCnt):
            data = CommFunc.WriteString(data, self.ViewIDDataList[i].GetLength(), self.ViewIDDataList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                Type:%d,
                                GroupValue1:%d,
                                GroupValue2:%d,
                                DataTotal:%d,
                                PageDataCnt:%d,
                                PageDataList:%s,
                                ViewID:%d,
                                ViewIDDataCnt:%d,
                                ViewIDDataList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.Type,
                                self.GroupValue1,
                                self.GroupValue2,
                                self.DataTotal,
                                self.PageDataCnt,
                                "...",
                                self.ViewID,
                                self.ViewIDDataCnt,
                                "..."
                                )
        return DumpString
m_NAtagMCViewBillboardRet=tagMCViewBillboardRet()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCViewBillboardRet.Head.Cmd,m_NAtagMCViewBillboardRet.Head.SubCmd))] = m_NAtagMCViewBillboardRet
#------------------------------------------------------
# A2 02 玩家攻击模式通知 #tagMCAttackMode
class  tagMCAttackMode(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBDataMgr.py
@@ -19,6 +19,7 @@
import PyGameData
import DBEventTrig
import DBPlayerViewCache
import DBBillboard
import DBFamily
import DBMail
@@ -46,9 +47,10 @@
    return
def OnMinute(curTime):
    curMinute = curTime.minute
    #curMinute = curTime.minute
    ServerDataBackup()
    DBFamily.OnMinute(curMinute)
    DBFamily.OnMinute()
    DBBillboard.OnMinute()
    return
#------------------------------------------- 备档 ---------------------------------------------------
@@ -165,6 +167,7 @@
        self.PlayerViewCacheMgr = DBPlayerViewCache.PlayerViewCacheMgr()
        self.FamilyMgr = DBFamily.FamilyMgr()
        self.MailMgr = DBMail.MailMgr()
        self.BillboardMgr = DBBillboard.BillboardMgr()
        return
    
    def GetSaveData(self):
@@ -173,6 +176,7 @@
        buff += self.PlayerViewCacheMgr.GetSaveData()
        buff += self.FamilyMgr.GetSaveData()
        buff += self.MailMgr.GetSaveData()
        buff += self.BillboardMgr.GetSaveData()
        return buff
    
    def LoadGameData(self, gameBuffer, pos):
@@ -181,6 +185,7 @@
        pos = self.PlayerViewCacheMgr.LoadPyGameData(gameBuffer, pos, dataslen)
        pos = self.FamilyMgr.LoadPyGameData(gameBuffer, pos, dataslen)
        pos = self.MailMgr.LoadPyGameData(gameBuffer, pos, dataslen)
        pos = self.BillboardMgr.LoadPyGameData(gameBuffer, pos, dataslen)
        return pos
    
def GetDBDataMgr():
@@ -215,3 +220,8 @@
    dbDataMgr = GetDBDataMgr()
    return dbDataMgr.MailMgr
def GetBillboardMgr():
    ## 排行榜数据管理器
    dbDataMgr = GetDBDataMgr()
    return dbDataMgr.BillboardMgr
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
@@ -1698,3 +1698,202 @@
        else:
            self.GUID = Str[:36]
            
# 排行榜表 #tagDBBillboard
class tagDBBillboard(Structure):
    _pack_ = 1
    _fields_ = [
        ('GroupValue1', ctypes.c_ulong),
        ('GroupValue2', ctypes.c_ulong),
        ('BillboardType', ctypes.c_ubyte),
        ('ID', ctypes.c_ulong),
        ('ID2', ctypes.c_ulong),
        ('Name1', ctypes.c_char * 33),
        ('Name2', ctypes.c_char * 65),
        ('Type2', ctypes.c_ubyte),
        ('Value1', ctypes.c_ulong),
        ('Value2', ctypes.c_ulong),
        ('Value3', ctypes.c_ulong),
        ('Value4', ctypes.c_ulong),
        ('Value5', ctypes.c_ulong),
        ('Value6', ctypes.c_ulong),
        ('Value7', ctypes.c_ulong),
        ('Value8', ctypes.c_ulong),
        ('CmpValue', ctypes.c_ulong),
        ('CmpValue2', ctypes.c_ulong),
        ('CmpValue3', ctypes.c_ulong),
        ('DataLen', ctypes.c_ushort),
        ('UserData', ctypes.c_char_p),
        ('ADOResult', ctypes.c_ulong),
    ]
    def __init__(self):
        Structure.__init__(self)
        self.clear()
    def clear(self):
        self.GroupValue1 = 0
        self.GroupValue2 = 0
        self.BillboardType = 0
        self.ID = 0
        self.ID2 = 0
        self.Name1 = ''
        self.Name2 = ''
        self.Type2 = 0
        self.Value1 = 0
        self.Value2 = 0
        self.Value3 = 0
        self.Value4 = 0
        self.Value5 = 0
        self.Value6 = 0
        self.Value7 = 0
        self.Value8 = 0
        self.CmpValue = 0
        self.CmpValue2 = 0
        self.CmpValue3 = 0
        self.DataLen = 0
        self.UserData = ''
    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.ReadDWORD(buf, pos)
        self.GroupValue2, pos = CommFunc.ReadDWORD(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, 65)
        self.Type2, pos = CommFunc.ReadBYTE(buf, pos)
        self.Value1, pos = CommFunc.ReadDWORD(buf, pos)
        self.Value2, pos = CommFunc.ReadDWORD(buf, pos)
        self.Value3, pos = CommFunc.ReadDWORD(buf, pos)
        self.Value4, pos = CommFunc.ReadDWORD(buf, pos)
        self.Value5, pos = CommFunc.ReadDWORD(buf, pos)
        self.Value6, pos = CommFunc.ReadDWORD(buf, pos)
        self.Value7, pos = CommFunc.ReadDWORD(buf, pos)
        self.Value8, 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)
        self.DataLen, pos = CommFunc.ReadWORD(buf, pos)
        tmp, pos = CommFunc.ReadString(buf, pos, self.DataLen)
        self.UserData = ctypes.c_char_p(tmp)
        return self.getLength()
    def getBuffer(self):
        buf = ''
        buf = CommFunc.WriteDWORD(buf, self.GroupValue1)
        buf = CommFunc.WriteDWORD(buf, self.GroupValue2)
        buf = CommFunc.WriteBYTE(buf, self.BillboardType)
        buf = CommFunc.WriteDWORD(buf, self.ID)
        buf = CommFunc.WriteDWORD(buf, self.ID2)
        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.Name1)
        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 65, self.Name2)
        buf = CommFunc.WriteBYTE(buf, self.Type2)
        buf = CommFunc.WriteDWORD(buf, self.Value1)
        buf = CommFunc.WriteDWORD(buf, self.Value2)
        buf = CommFunc.WriteDWORD(buf, self.Value3)
        buf = CommFunc.WriteDWORD(buf, self.Value4)
        buf = CommFunc.WriteDWORD(buf, self.Value5)
        buf = CommFunc.WriteDWORD(buf, self.Value6)
        buf = CommFunc.WriteDWORD(buf, self.Value7)
        buf = CommFunc.WriteDWORD(buf, self.Value8)
        buf = CommFunc.WriteDWORD(buf, self.CmpValue)
        buf = CommFunc.WriteDWORD(buf, self.CmpValue2)
        buf = CommFunc.WriteDWORD(buf, self.CmpValue3)
        buf = CommFunc.WriteWORD(buf, self.DataLen)
        buf = CommFunc.WriteString(buf, self.DataLen, self.UserData)
        return buf
    def getLength(self):
        length = 0
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_char) * 33
        length += sizeof(ctypes.c_char) * 65
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ushort)
        length += self.DataLen
        return length
    def outputString(self):
        output = '''// 排行榜表 #tagDBBillboard:
            GroupValue1 = %s,
            GroupValue2 = %s,
            BillboardType = %s,
            ID = %s,
            ID2 = %s,
            Name1 = %s,
            Name2 = %s,
            Type2 = %s,
            Value1 = %s,
            Value2 = %s,
            Value3 = %s,
            Value4 = %s,
            Value5 = %s,
            Value6 = %s,
            Value7 = %s,
            Value8 = %s,
            CmpValue = %s,
            CmpValue2 = %s,
            CmpValue3 = %s,
            DataLen = %s,
            UserData = %s,
            ADOResult = %s,
            '''%(
                self.GroupValue1,
                self.GroupValue2,
                self.BillboardType,
                self.ID,
                self.ID2,
                self.Name1,
                self.Name2,
                self.Type2,
                self.Value1,
                self.Value2,
                self.Value3,
                self.Value4,
                self.Value5,
                self.Value6,
                self.Value7,
                self.Value8,
                self.CmpValue,
                self.CmpValue2,
                self.CmpValue3,
                self.DataLen,
                self.UserData,
                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)<=65:
            self.Name2 = Str
        else:
            self.Name2 = Str[:65]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBBillboard.py
New file
@@ -0,0 +1,453 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package DB.StructData.DBBillboard
#
# @todo:DB排行榜
# @author hxp
# @date 2025-05-16
# @version 1.0
#
# 详细描述: DB排行榜
#
#-------------------------------------------------------------------------------
#"""Version = 2025-05-16 12:00"""
#-------------------------------------------------------------------------------
import DBStruct
import GameWorld
import ShareDefine
import DataRecordPack
import IpyGameDataPY
import DBDataMgr
import CommFunc
import json
class BillboardData():
    ## 榜单数据
    def __init__(self, dbData=None):
        self.__dbData = DBStruct.tagDBBillboard() if not dbData else dbData
        return
    def GetType(self): return self.__dbData.BillboardType
    def SetType(self, bType): self.__dbData.BillboardType = bType
    def GetGroupValue1(self): return self.__dbData.GroupValue1
    def SetGroupValue1(self, groupValue1): self.__dbData.GroupValue1 = groupValue1
    def GetGroupValue2(self): return self.__dbData.GroupValue2
    def SetGroupValue2(self, groupValue2): self.__dbData.GroupValue2 = groupValue2
    def GetID(self): return self.__dbData.ID
    def SetID(self, dataID): self.__dbData.ID = dataID
    def GetID2(self): return self.__dbData.ID2
    def SetID2(self, id2): self.__dbData.ID2 = id2
    def GetName1(self): return self.__dbData.Name1
    def SetName1(self, name): self.__dbData.Name1 = name
    def GetName2(self): return self.__dbData.Name2
    def SetName2(self, name2): self.__dbData.Name2 = name2
    def GetType2(self): return self.__dbData.Type2
    def SetType2(self, type2): self.__dbData.Type2 = type2
    def GetValue1(self): return self.__dbData.Value1
    def SetValue1(self, value1): self.__dbData.Value1 = value1
    def GetValue2(self): return self.__dbData.Value2
    def SetValue2(self, value2): self.__dbData.Value2 = value2
    def GetValue3(self): return self.__dbData.Value3
    def SetValue3(self, value3): self.__dbData.Value3 = value3
    def GetValue4(self): return self.__dbData.Value4
    def SetValue4(self, value4): self.__dbData.Value4 = value4
    def GetValue5(self): return self.__dbData.Value5
    def SetValue5(self, value5): self.__dbData.Value5 = value5
    def GetValue6(self): return self.__dbData.Value6
    def SetValue6(self, value6): self.__dbData.Value6 = value6
    def GetValue7(self): return self.__dbData.Value7
    def SetValue7(self, value7): self.__dbData.Value7 = value7
    def GetValue8(self): return self.__dbData.Value8
    def SetValue8(self, value8): self.__dbData.Value8 = value8
    def GetCmpValue(self): return self.__dbData.CmpValue
    def SetCmpValue(self, cmpValue): self.__dbData.CmpValue = cmpValue
    def GetCmpValue2(self): return self.__dbData.CmpValue2
    def SetCmpValue2(self, cmpValue2): self.__dbData.CmpValue2 = cmpValue2
    def GetCmpValue3(self): return self.__dbData.CmpValue3
    def SetCmpValue3(self, cmpValue3): self.__dbData.CmpValue3 = cmpValue3
    def GetUserData(self): return self.__dbData.UserData
    def SetUserData(self, userData):
        if not isinstance(userData, str):
            if isinstance(userData, dict) or isinstance(userData, list):
                userData = json.dumps(userData, ensure_ascii=False)
            else:
                userData = ""
        userData = userData.replace(" ", "")
        self.__dbData.UserData = userData
        self.__dbData.DataLen = len(self.__dbData.UserData)
        return
    def GetBuffer(self): return self.__dbData.getBuffer()
    def Clear(self): return self.__dbData.clear()
    def Copy(self, setType=None):
        copyData = BillboardData()
        copyData.SetType(setType if setType != None else self.GetType())
        copyData.SetGroupValue1(self.GetGroupValue1())
        copyData.SetGroupValue2(self.GetGroupValue2())
        copyData.SetID(self.GetID())
        copyData.SetID2(self.GetID2())
        copyData.SetName1(self.GetName1())
        copyData.SetName2(self.GetName2())
        copyData.SetType2(self.GetType2())
        copyData.SetValue1(self.GetValue1())
        copyData.SetValue2(self.GetValue2())
        copyData.SetValue3(self.GetValue3())
        copyData.SetValue4(self.GetValue4())
        copyData.SetValue5(self.GetValue5())
        copyData.SetValue6(self.GetValue6())
        copyData.SetValue7(self.GetValue7())
        copyData.SetValue8(self.GetValue8())
        copyData.SetUserData(self.GetUserData())
        copyData.SetCmpValue(self.GetCmpValue())
        copyData.SetCmpValue2(self.GetCmpValue2())
        copyData.SetCmpValue3(self.GetCmpValue3())
        return copyData
class Billboard():
    ## 某个排行榜类
    def __init__(self, billboardType=0, groupValue1=0, groupValue2=0):
        self.__billboardType = billboardType
        self.__groupValue1 = groupValue1
        self.__groupValue2 = groupValue2
        self.__billboardList = [] # [BillboardData, ...]
        self.__idIndexDict = {} # {id:index, ...}
        self.__idOrderDict = {} # {id:名次, ...}
        self.__orderRuleList = None # 指定排名所需值规则列表 [[order, needCmpValue], ...]
        self.__sortDelay = False # 是否需要延迟排序
        return
    def GetType(self): return self.__billboardType
    def GetGroupValue1(self): return self.__groupValue1
    def GetGroupValue2(self): return self.__groupValue2
    def ClearData(self):
        if not self.__billboardList:
            return
        GameWorld.Log("Billboard ClearData billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s"
                      % (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList)))
        if GameWorld.IsCrossServer():
            self.SaveDRData("Clear")
        self.__billboardList = [] # [BillboardData, ...]
        self.__idOrderDict = {} # {id:名次, ...}
        self.__idIndexDict = {}
        return
    def SortData(self):
        GameWorld.DebugLog("榜单排序: billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s"
                      % (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList)))
        self.__billboardList.sort(key=lambda b: (b.GetCmpValue(), b.GetCmpValue2(), b.GetCmpValue3()), reverse=True)
        self.__idOrderDict = {} # 排序后重置,下次查询时更新并缓存
        self.__idIndexDict = {}
        self.__sortDelay = False
        return
    def SetSortDelay(self):
        ## 设置延迟排序
        GameWorld.DebugLog("榜单设置延迟排序: billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s"
                      % (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList)))
        self.__sortDelay = True
        return
    def SortDelayDo(self):
        ## 延迟排序执行排序
        if not self.__sortDelay:
            return
        self.SortData()
        return
    def AddNewBillboardData(self):
        newData = None
        if self.IsFull():
            return newData
        newData = BillboardData()
        newData.SetType(self.__billboardType)
        newData.SetGroupValue1(self.__groupValue1)
        newData.SetGroupValue2(self.__groupValue2)
        self.AddBillboardData(newData)
        return newData
    def AddBillboardData(self, billboardData):
        ## 添加榜单数据到该榜
        # @param billboardData: BillboardData
        # @return: 是否成功
        if self.IsFull():
            return False
        self.__billboardList.append(billboardData)
        self.__idIndexDict[billboardData.GetID()] = len(self.__billboardList) - 1
        self.__sortDelay = True
        # __idOrderDict 不处理,等下次排序后自动处理,所以新添加的数据可能找不到对应名次,但是能找到对应索引及数据
        return True
    def FindByID(self, findID):
        ''' 根据ID查询榜单数据
        @param findID: 查找的ID
        @return: None or BillboardData
        '''
        billData = None
        self.GetIDOrderDict()
        if findID not in self.__idIndexDict:
            return billData
        idIndex = self.__idIndexDict[findID]
        if idIndex >= len(self.__billboardList):
            return billData
        billData = self.__billboardList[idIndex]
        if not billData and False:
            billData = BillboardData() # 不会执行到,只为了.出代码提示
        return billData
    def IndexOfByID(self, findID):
        ''' 根据ID查询所在榜单索引
        @param findID: 查找的ID
        @return: -1 or >=0
        '''
        self.GetIDOrderDict()
        if findID not in self.__idIndexDict:
            return -1
        idIndex = self.__idIndexDict[findID]
        return idIndex
    def SaveDRData(self, eventName="", addDataDict={}):
        ## 记录流向数据
        self.SortDelayDo()
        dataCount = len(self.__billboardList)
        if not dataCount:
            return
        idOrderDict = self.GetIDOrderDict()
        serverTime = GameWorld.GetServerTime()
        timeStr = "%02d%02d%02d%s" % (serverTime.hour, serverTime.minute, serverTime.second, str(serverTime.microsecond)[:3])
        eventTypeStr = "Billboard_%s_%s_%s_%s_%s" % (self.__billboardType, self.__groupValue1, self.__groupValue2, eventName, timeStr)
        dataDict = {"BillboardType":self.__billboardType, "DataCount":dataCount, "addDataDict":addDataDict,
                    "GroupValue1":self.__groupValue1, "GroupValue2":self.__groupValue2}
        DataRecordPack.SendEventPack(eventTypeStr, dataDict)
        for index, bData in enumerate(self.__billboardList):
            rank = idOrderDict.get(bData.GetID(), index + 1)
            dataDict = {"Type2":bData.GetType2(), "Rank":rank, "Index":index,
                        "ID":bData.GetID(), "ID2":bData.GetID2(),
                        "Name1":bData.GetName1(), "Name2":bData.GetName2(),
                        "Value1":bData.GetValue1(), "Value2":bData.GetValue2(),
                        "Value3":bData.GetValue3(), "Value4":bData.GetValue4(),
                        "Value5":bData.GetValue5(), "Value6":bData.GetValue6(),
                        "Value7":bData.GetValue7(), "Value8":bData.GetValue8(),
                        "CmpValue":bData.GetCmpValue(), "CmpValue2":bData.GetCmpValue2(),
                        "CmpValue3":bData.GetCmpValue3(), "UserData":bData.GetUserData()}
            DataRecordPack.SendEventPack(eventTypeStr, dataDict)
        return
    def GetBillboardDataList(self): return self.__billboardList
    def GetIDOrderDict(self):
        ## 获取ID对应名次字典
        # @return: {ID:名次, ...}  名次从1开始
        if not self.__idOrderDict or not self.__idIndexDict:
            self.__idOrderDict = {}
            self.__idIndexDict = {}
            if self.__orderRuleList:
                billboardDataCount = self.GetCount()
                rankPre = 0
                billboardIndex = 0
                for rank, needCmpValue in self.__orderRuleList:
                    orderCountTotal = rank - rankPre # 奖励名次数量
                    rankPre = rank
                    for index in xrange(billboardIndex, billboardDataCount):
                        if orderCountTotal <= 0:
                            break
                        billboardData = self.At(index)
                        if billboardData.GetCmpValue() < needCmpValue:
                            break
                        orderReal = rank - orderCountTotal + 1
                        self.__idOrderDict[billboardData.GetID()] = orderReal
                        orderCountTotal -= 1
                        billboardIndex += 1
                for order, billboardData in enumerate(self.__billboardList, 1):
                    self.__idIndexDict[billboardData.GetID()] = order - 1
            else:
                for order, billboardData in enumerate(self.__billboardList, 1):
                    self.__idOrderDict[billboardData.GetID()] = order
                    self.__idIndexDict[billboardData.GetID()] = order - 1
        return self.__idOrderDict
    def SetOrderRuleList(self, orderRuleList):
        ## 排名所需值规则列表
        # @param orderRuleList: 排名所需值规则列表 [[order, needCmpValue], ...]
        self.__orderRuleList = orderRuleList
        self.__idOrderDict = {} # 设置后需重置,可能配置规则变化了导致实际排名可能变化
        self.__idIndexDict = {}
        GameWorld.Log("设置排名所需值规则列表: billboardType=%s,groupValue1=%s,groupValue2=%s, %s"
                      % (self.__billboardType, self.__groupValue1, self.__groupValue2, orderRuleList))
        return
    def GetCount(self): return len(self.__billboardList)
    def GetMaxCount(self):
        maxCountDict = IpyGameDataPY.GetFuncEvalCfg("BillboardSet", 2, {})
        return maxCountDict.get(self.__billboardType, 100)
    def At(self, index):
        billData = self.__billboardList[index]
        if not billData and False:
            billData = BillboardData() # 不会执行到,只为了.出代码提示
        return billData
    def IsFull(self): return len(self.__billboardList) >= self.GetMaxCount()
    def DeleteByIndex(self, index):
        if index >= len(self.__billboardList):
            return
        self.__billboardList.pop(index)
        self.__idOrderDict = {}
        self.__idIndexDict = {}
        return
    def DeleteByID(self, dataID):
        index = self.IndexOfByID(dataID)
        if index >= 0:
            self.DeleteByIndex(index)
        return
class BillboardMgr():
    ## 排行榜管理
    def __init__(self):
        self.__billboardDict = {} # 排行榜字典 {(billboardType, groupValue1, groupValue2):Billboard, ...}
        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 GetBillboard(self, billboardType, groupValue1=0, groupValue2=0):
        ''' 获取排行榜
        @param billboardType: 排行榜类型
        @param groupValue1: 分组值1
        @param groupValue2: 分组值2,与分组值1组合归为同组榜单数据
        @return: Billboard
        '''
        key = (billboardType, groupValue1, groupValue2)
        if key in self.__billboardDict:
            billboardObj = self.__billboardDict[key]
        else:
            billboardObj = Billboard(billboardType, groupValue1, groupValue2)
            self.__billboardDict[key] = billboardObj
        return billboardObj
    def RemoveBillboard(self, billboardType):
        ## 移除某个类型的榜单所有数据
        for key in self.__billboardDict.keys():
            if key[0] == billboardType:
                self.__billboardDict.pop(key)
        return
    def ClearBillboard(self, billboardType, groupValue1=None, groupValue2=None):
        '''清除某个类型的榜单所有数据,可指定过滤groupValue,有流向记录
        @param groupValue1: 不为None时验证 groupValue1 是否相同
        @param groupValue2: 不为None时验证 groupValue2 是否相同
        如果groupValue1 groupValue2 都传入None,相当于清空 billboardType 类型的所有榜单数据
        '''
        clearList = []
        for bType, gValue1, gValue2 in self.__billboardDict.keys():
            if bType != billboardType:
                continue
            if groupValue1 != None and groupValue1 != gValue1:
                continue
            if groupValue2 != None and groupValue2 != gValue2:
                continue
            key = (bType, gValue1, gValue2)
            clearList.append(key)
        for bType, gValue1, gValue2 in clearList:
            self.GetBillboard(bType, gValue1, gValue2).ClearData()
        return
    def CopyBillboard(self, fromBillboardType, toBillboardType, groupValue1=None, groupValue2=None):
        '''将某个类型的榜单完全拷贝到其他榜单 - 一般用于备份、转移数据
        @param fromBillboardType: 源榜单类型
        @param toBillboardType: 目标榜单类型
        @param groupValue1: 默认为None-拷贝该类型所有榜单,大于等于0时-仅拷贝该类型下的指定榜单
        @param groupValue2: 默认为None-拷贝该类型所有榜单,大于等于0时-仅拷贝该类型下的指定榜单
        '''
        if groupValue1 == None:
            self.RemoveBillboard(toBillboardType) # 默认清空目标榜单
            groupList = self.GetBillboardGroupList(fromBillboardType)
        else:
            groupValue2 = groupValue2 if groupValue2 != None else 0
            groupList = [fromBillboardType, groupValue1, groupValue2]
        for billboardType, groupValue1, groupValue2 in groupList:
            frbillboardObj = self.GetBillboard(billboardType, groupValue1, groupValue2)
            toBillboardObj = self.GetBillboard(toBillboardType, groupValue1, groupValue2)
            GameWorld.Log("CopyBillboard: billboardType=%s,toBillboardType=%s,groupValue1=%s,groupValue2=%s"
                          % (billboardType, toBillboardType, groupValue1, groupValue2))
            toBillboardObj.ClearData()
            for index in range(frbillboardObj.GetCount()):
                frbillboardData = frbillboardObj.At(index)
                toBillboardObj.AddBillboardData(frbillboardData.Copy(toBillboardType))
        return
    # 保存数据 存数据库和realtimebackup
    def GetSaveData(self):
        savaData = ""
        cntData = ""
        cnt = 0
        for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys():
            billboardObj = self.GetBillboard(billboardType, groupValue1, groupValue2)
            for i in xrange(billboardObj.GetCount()):
                billboardData = billboardObj.At(i)
                cnt += 1
                savaData += billboardData.GetBuffer()
        GameWorld.Log("Save DBBillboard count :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
    # 从数据库载入数据
    def LoadPyGameData(self, datas, pos, dataslen):
        if pos >= dataslen:
            return
        cnt, pos = CommFunc.ReadDWORD(datas, pos)
        GameWorld.Log("Load DBBillboard count :%s" % cnt)
        for _ in xrange(cnt):
            dbData = DBStruct.tagDBBillboard()
            dbData.clear()
            pos += dbData.readData(datas, pos, dataslen)
            billboardType, groupValue1, groupValue2 = dbData.BillboardType, dbData.GroupValue1, dbData.GroupValue2
            billboardObj = self.GetBillboard(billboardType, groupValue1, groupValue2)
            billboardObj.AddBillboardData(BillboardData(dbData))
        # 排序
        for billboardType, groupValue1, groupValue2 in self.__billboardDict.keys():
            billboardObj = self.GetBillboard(billboardType, groupValue1, groupValue2)
            billboardObj.SortData()
        return pos
def OnMinute():
    ## 每分钟延迟排序
    billboardMgr = DBDataMgr.GetBillboardMgr()
    for billboardType in ShareDefine.BillboardTypeAllList:
        groupList = billboardMgr.GetBillboardGroupList(billboardType)
        for billboardType, groupValue1, groupValue2 in groupList:
            billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
            billboardObj.SortDelayDo()
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
@@ -630,7 +630,7 @@
            
        return pos
    
def OnMinute(curMinute):
def OnMinute():
    
    familyMgr = DBDataMgr.GetFamilyMgr()
    # 每分钟刷新下仙盟战力排序
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py
New file
@@ -0,0 +1,187 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GM.Commands.Billboard
#
# @todo:榜单数据
# @author hxp
# @date 2025-05-16
# @version 1.0
#
# 详细描述: 榜单数据
#
#-------------------------------------------------------------------------------
#"""Version = 2025-05-16 12:00"""
#-------------------------------------------------------------------------------
import GameWorld
import PlayerBillboard
import ShareDefine
import DBDataMgr
def __Help(curPlayer, errInfo=""):
    GameWorld.DebugAnswer(curPlayer, "---------- %s" % GameWorld.GetCurrentDataTimeStr())
    if errInfo:
        GameWorld.DebugAnswer(curPlayer, errInfo)
    GameWorld.DebugAnswer(curPlayer, "新增榜单假数据: Billboard 类型 分组值1 分组值2 条数 比较值1可选参数(比较值2 常规值1~5)")
    GameWorld.DebugAnswer(curPlayer, "删除榜单假数据: Billboard 类型 分组值1 分组值2")
    GameWorld.DebugAnswer(curPlayer, "榜单类型:0-战力,1-龙魂,2-灵瑶,4-等级,5-坐骑,6-灵宠,7-符印,8-脱机,9-境界,19-助战")
    GameWorld.DebugAnswer(curPlayer, "开服活动榜类型:11-强化,12-坐骑,13-宝石,14-冲级,15-境界,16-战力,18-符印,20-神兵,21-充值,22-灵宠,24-灵根,25-升星,26-洗练")
    GameWorld.DebugAnswer(curPlayer, "运营活动榜类型:17-仙界盛典,23-仙界盛典2,33-boss凭证,36-boss凭证仙盟,38-仙匣,39-古宝,40-骑宠")
    GameWorld.DebugAnswer(curPlayer, "魅力榜单类型:30-总榜,31-周榜,32-日榜")
    GameWorld.DebugAnswer(curPlayer, "运营活动榜类型:150-充值(分组值1配置ID)")
    GameWorld.DebugAnswer(curPlayer, "运营活动榜类型:158-boss凭证,160-凭证仙盟,162-仙匣,163-古宝,164-骑宠")
    GameWorld.DebugAnswer(curPlayer, "古神战场榜类型:151-参与榜,152-召集榜,153-积分榜")
    GameWorld.DebugAnswer(curPlayer, "逐鹿万界榜类型:156-单场榜,157-周榜")
    GameWorld.DebugAnswer(curPlayer, "跨服竞技场榜单:165,分组值1-分区,分组值2-赛季,value2-段位")
    GameWorld.DebugAnswer(curPlayer, "注:如果没有特殊说明,本服榜单分组值均为0,跨服榜单分组值1为分区ID,分组2为0")
    return
## 执行逻辑
#  @param curPlayer 当前玩家
#  @param gmList []
#  @return None
def OnExec(curPlayer, gmList):
    paramLen = len(gmList)
    if not paramLen:
        __Help(curPlayer)
        return
    value = gmList[0]
    if value == "p":
        __logFackData(curPlayer, gmList)
        return
    billboardIndex = value
    if billboardIndex >= ShareDefine.BillboardTypeAllList:
        __Help(curPlayer, "榜单类型不存在!")
        return
    if billboardIndex in ShareDefine.CrossBillboardTypeList:
        GameWorld.DebugAnswer(curPlayer, "跨服榜单暂不处理")
        return
    if len(gmList) <= 3:
        __delFackData(curPlayer, gmList)
    else:
        __addFackData(curPlayer, gmList)
    return
def __addFackData(curPlayer, gmList):
    ## 新增榜单假数据: Billboard 类型 分组值1 分组值2 条数 比较值1可选参数(比较值2 常规值1~5)
    billboardType = gmList[0]
    groupValue1 = gmList[1] if len(gmList) > 1 else 0
    groupValue2 = gmList[2] if len(gmList) > 2 else 0
    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
    value3 = gmList[8] if len(gmList) > 8 else 0
    value4 = gmList[9] if len(gmList) > 9 else 0
    value5 = gmList[10] if len(gmList) > 10 else 0
    id2 = 0
    type2 = 0
    name2 = ""
    cmpValue3 = 0
    billboardMgr = DBDataMgr.GetBillboardMgr()
    billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
    curDataCount = billboardObj.GetCount()
    maxDataCount = billboardObj.GetMaxCount()
    count = min(count, maxDataCount - curDataCount)
    FakeName = GameWorld.GbkToCode("假名字")
    for i in xrange(count):
        dataPlayerID = curDataCount + 1 + i
        dataPlayerName = "%s%s" % (FakeName, dataPlayerID)
        dataCmpValue1 = max(0, cmpValue1 - i)
        dataCmpValue2 = max(0, cmpValue2 - i)
        dataID = dataPlayerID
        name1 = dataPlayerName
        cmpValue = dataCmpValue1
        cmpValue2 = dataCmpValue2
        PlayerBillboard.UpdateBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2,
                                        cmpValue, cmpValue2, cmpValue3, groupValue2, id2, False,
                                        value3=value3, value4=value4, value5=value5)
    billboardObj.SortData()
    billTypeSign = __GetBillTypeSign(billboardType, groupValue1, groupValue2)
    GameWorld.DebugAnswer(curPlayer, "插入假榜单(%s): %s 条" % (billTypeSign, count))
    return
def __delFackData(curPlayer, gmList):
    ## 删除榜单假数据
    billboardType = gmList[0]
    groupValue1 = gmList[1] if len(gmList) > 1 else 0
    groupValue2 = gmList[2] if len(gmList) > 2 else 0
    billboardMgr = DBDataMgr.GetBillboardMgr()
    billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
    curDataCount = billboardObj.GetCount()
    maxDataCount = billboardObj.GetMaxCount()
    delCount = 0
    for index in range(curDataCount)[::-1]:
        billData = billboardObj.At(index)
        if billData.GetID() <= maxDataCount:
            billboardObj.DeleteByIndex(index)
            delCount += 1
    billTypeSign = __GetBillTypeSign(billboardType, groupValue1, groupValue2)
    GameWorld.DebugAnswer(curPlayer, "删除假榜单(%s): %s 条, 剩: %s" % (billTypeSign, delCount, billboardObj.GetCount()))
    return
def __GetBillTypeSign(billboardType, groupValue1, groupValue2):
    billTypeSign = "%s" % billboardType
    if groupValue1:
        billTypeSign = "%s-%s" % (billTypeSign, groupValue1)
    if groupValue2:
        billTypeSign = "%s-%s" % (billTypeSign, groupValue2)
    return billTypeSign
def __logFackData(curPlayer, gmList):
    ## 输出排行榜数据: Billboard p 类型 分组值1 分组值2
    if len(gmList) <= 1:
        GameWorld.DebugAnswer(curPlayer, "榜单数据条数总览")
        billboardMgr = DBDataMgr.GetBillboardMgr()
        for bType in ShareDefine.BillboardTypeAllList:
            groupList = billboardMgr.GetBillboardGroupList(bType)
            for bType, groupValue1, groupValue2 in groupList:
                billboardObj = billboardMgr.GetBillboard(bType, groupValue1, groupValue2)
                curDataCount = billboardObj.GetCount()
                maxDataCount = billboardObj.GetMaxCount()
                if not curDataCount:
                    continue
                billTypeSign = __GetBillTypeSign(bType, groupValue1, groupValue2)
                GameWorld.DebugAnswer(curPlayer, "榜单数据(%s)条数: %s/%s" % (billTypeSign, curDataCount, maxDataCount))
        return
    billboardType = gmList[1]
    groupValue1 = gmList[2] if len(gmList) > 2 else 0
    groupValue2 = gmList[3] if len(gmList) > 3 else 0
    billboardMgr = DBDataMgr.GetBillboardMgr()
    billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
    billboardObj.SortDelayDo()
    curDataCount = billboardObj.GetCount()
    maxDataCount = billboardObj.GetMaxCount()
    idOrderDict = billboardObj.GetIDOrderDict()
    billTypeSign = __GetBillTypeSign(billboardType, groupValue1, groupValue2)
    GameWorld.DebugAnswer(curPlayer, "榜单数据(%s)条数: %s/%s 详见日志" % (billTypeSign, curDataCount, maxDataCount))
    for index in range(curDataCount):
        bbData = billboardObj.At(index)
        dataID = bbData.GetID()
        rank = idOrderDict.get(dataID, 0)
        valueList = [getattr(bbData, "GetValue%s" % num)() for num in range(1, 9)]
        GameWorld.DebugLog("%s,rank=%s,ID=%s,CmpValue=%s,CmpValue2=%s,Value=%s"
                           % (index, rank, dataID, bbData.GetCmpValue(), bbData.GetCmpValue2(), valueList), curPlayer.GetPlayerID())
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
@@ -866,6 +866,8 @@
# @remarks 获得服务器系统时间
def GetCurrentTime():
    return datetime.datetime.today()
def GetServerTime():
    return datetime.datetime.today()
#    ctime = GetGameWorld().GetGameServerEventTime()
#    
#    if not ctime:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -1541,9 +1541,6 @@
        #更改镖车记录的部分主人信息
        PlayerTruck.ChangeTruckNoteInfo(curPlayer)
        
        #更新镖车进排行榜
        PlayerBillboard.UpdateBillboardPlayerTruck(curPlayer.GetPlayerID(), curPlayer.GetName(), curPlayer.GetOperateInfo(),
                                                   curPlayer.GetLV(), truckLv, curPlayer.GetMapID())
    #---初始化自己的召唤兽---
    #===========================================================================
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
@@ -9,20 +9,43 @@
# @date 2018-03-06
# @version 1.0
#
# 详细描述: 排行榜
# 详细描述: 排行榜,本服、跨服通用
#
#-------------------------------------------------------------------------------
#"""Version = 2018-03-06 11:00"""
#-------------------------------------------------------------------------------
import ShareDefine
import GameWorld
import ChConfig
import GameWorld
import ShareDefine
import PlayerControl
import OpenServerCampaign
import CrossRealmPlayer
import ChPyNetSendPack
import NetPackCommon
import IpyGameDataPY
import GameFuncComm
import EventReport
import DBDataMgr
import time
def OnDay():
    drBillboardTypeList = []
    if GameWorld.IsCrossServer():
        drBillboardTypeList = ShareDefine.CrossBillboardTypeList
    else:
        drBillboardTypeList = IpyGameDataPY.GetFuncEvalCfg("BillboardSet", 1)
    billboardMgr = DBDataMgr.GetBillboardMgr()
    for billboardType in drBillboardTypeList:
        if billboardType in [ShareDefine.Def_CBT_BossTrialSubmitBak, ShareDefine.Def_CBT_BossTrialSubmitFamilyBak, ShareDefine.Def_CBT_CrossRealmPK]:
            continue
        groupList = billboardMgr.GetBillboardGroupList(billboardType)
        for billboardType, groupValue1, groupValue2 in groupList:
            billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
            billboardObj.SaveDRData("OnDay")
    return
def DoBillboardOpen(curPlayer):
    ## 排行榜开启时需要处理的
@@ -30,11 +53,14 @@
    OpenServerCampaign.DoBillboardOpen(curPlayer) # 同步开服活动榜单
    return
def BillboardOnLogin(curPlayer):
    # 上线默认同步排行榜
    UpdatePlayerBillboardOnLeaveServer(curPlayer) #排行榜已实时更新,故上线不再同步
    return
def GetBillboardOperateInfo(curPlayer):
    # 排行榜中所保存的运营商相关信息
    platform = curPlayer.GetAccID()
    if platform in ["tencent"]:
        return curPlayer.GetOperateInfo()
    return platform
def GetBillboardJob(curPlayer): return curPlayer.GetJob()
@@ -44,7 +70,6 @@
    if GameWorld.IsCrossServer():
        # 跨服服务器不用更新本服榜
        return
    #UpdateTotalRechargeBillboard(curPlayer)
    
    UpdatePlayerLVBillboard(curPlayer) # 等级榜
    UpdatePlayerFPTotalBillboard(curPlayer, True) # 战斗力榜
@@ -55,116 +80,13 @@
    if isAll:
        UpdateRuneTowerBillboard(curPlayer)
        
        #UpdateTJGBillboard(curPlayer, minuteExp) 脱机效率可不更新
    EventReport.WriteEvent_FightPower(curPlayer)
    return
def __CanPlayerBillboardComm(curPlayer):
    ## 玩家可否上榜通用检查
    if not GameWorld.IsNormalPlayer(curPlayer):
        return False
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Billboard):
        GameWorld.DebugLog("排行榜未开启,无法上榜!curLV=%s" % (curPlayer.GetLV()), curPlayer.GetPlayerID())
        return False
    return True
def UpdatePlayerBillboard(curPlayer, bType, cmpValue, cmpValue2=0, cmpValue3=0, value1=0, value2=0, exInfo=[], autoSort=False, **kwargs):
    ## 更新玩家排行榜
    #if not cmpValue and not cmpValue2 and not cmpValue3:
    #    return
    if not __CanPlayerBillboardComm(curPlayer):
        return
    playerJob = GetBillboardJob(curPlayer)
    playerID = curPlayer.GetID()
    playerName = curPlayer.GetName()
    playerOpInfo = GetBillboardOperateInfo(curPlayer)
    kwargs["value3"] = curPlayer.GetFace()
    kwargs["value4"] = curPlayer.GetFacePic()
    if bType in ShareDefine.BTValue1_OfficialRankList:
        value1 = curPlayer.GetOfficialRank()
    GameServer_UpdateBillboard(bType, playerJob, playerID, playerName, playerOpInfo,
                               value1, value2, cmpValue, cmpValue2, cmpValue3, 0, exInfo, autoSort, **kwargs)
    return
def GameServer_UpdateBillboard(bType, bType2, bID, bName, bName2, value1, value2, cmpValue, cmpValue2=0, cmpValue3=0, bID2=0, exInfo=[], autoSort=False, **kwargs):
    bData = {"Type":bType, "Type2":bType2, "ID":bID, "ID2":bID2, "Name1":bName, "Name2":bName2, "ExInfo":exInfo,
             "Value1":value1, "Value2":value2, "CmpValue":cmpValue, "CmpValue2":cmpValue2, "CmpValue3":cmpValue3, "autoSort":autoSort}
    if "value3" in kwargs:
        bData["Value3"] = kwargs["value3"]
    if "value4" in kwargs:
        bData["Value4"] = kwargs["value4"]
    if "value5" in kwargs:
        bData["Value5"] = kwargs["value5"]
    if "value6" in kwargs:
        bData["Value6"] = kwargs["value6"]
    if "value7" in kwargs:
        bData["Value7"] = kwargs["value7"]
    if "value8" in kwargs:
        bData["Value8"] = kwargs["value8"]
    if "userData" in kwargs:
        bData["UserData"] = kwargs["userData"]
    sendMsg = "%s" % (bData)
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "UpdateBillboard", sendMsg, len(sendMsg))
    GameWorld.DebugLog("同步GameServer排行榜:bType=%s,cmpValue=%s,cmpValue2=%s %s" % (bType, cmpValue, cmpValue2, sendMsg), bID)
    return
def UpdatePlayerCrossBillboard(curPlayer, bType, groupValue1, cmpValue, cmpValue2=0, cmpValue3=0, value1=0, value2=0,
                               groupValue2=0, **kwargs):
    ## 更新玩家跨服排行榜
    #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)
    kwargs["value3"] = curPlayer.GetFace()
    kwargs["value4"] = curPlayer.GetFacePic()
    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, **kwargs)
    return
def GameServer_UpdateCrossBillboard(bType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,
                                    cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, **kwargs):
    bData = {"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 "value3" in kwargs:
        bData["Value3"] = kwargs["value3"]
    if "value4" in kwargs:
        bData["Value4"] = kwargs["value4"]
    if "value5" in kwargs:
        bData["Value5"] = kwargs["value5"]
    if "value6" in kwargs:
        bData["Value6"] = kwargs["value6"]
    if "value7" in kwargs:
        bData["Value7"] = kwargs["value7"]
    if "value8" in kwargs:
        bData["Value8"] = kwargs["value8"]
    if "userData" in kwargs:
        bData["UserData"] = kwargs["userData"]
    sendMsg = "%s" % (bData)
    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):
    ##更新玩家总战斗力
    
    playerFightPower = PlayerControl.GetFightPower(curPlayer)
    if not __CheckFightPowerCanUpdate(curPlayer, ChConfig.Def_PDict_FightPower_Total, playerFightPower,
    if not __CheckFightPowerCanUpdate(curPlayer, ChConfig.Def_PDict_FightPower_Total, playerFightPower,
                                      isForceUpdate, isCheckRule, ChConfig.Def_PDict_FightPower_TotalEx):
        return
    
@@ -174,11 +96,29 @@
                                       ChConfig.Def_PDictType_FightPower)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_TotalEx, fightPowerEx,
                                       ChConfig.Def_PDictType_FightPower)
    familyID = curPlayer.GetFamilyID()
    GameWorld.DebugLog("更新总战斗力:playerFightPower=%s" % (playerFightPower), curPlayer.GetPlayerID())
    
    UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_FightPower, fightPowerEx, fightPower, exInfo=[familyID])
    #EventReport.WriteEvent_FightPower(curPlayer)
    UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_FightPower, fightPowerEx, fightPower)
#    if bType == ShareDefine.Def_BT_FightPower:
#        playerID = bID
#        fightPowerTotal = cmpValue * ChConfig.Def_PerPointValue + cmpValue2
#        familyID = exInfo[0]
#        playerJob = bType2
#
#        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
#        if curPlayer:
#            PlayerControl.SetFightPower(curPlayer, fightPowerTotal)
#
#        #更新战盟成员战力
#        PlayerFamily.UpdFamilyMemberFightPower(familyID, playerID, fightPowerTotal)
#
#        #职业战力榜
#        job = playerJob % 10
#        if job in ShareDefine.JobFightPowerBillboardDict:
#            jobBType = ShareDefine.JobFightPowerBillboardDict[job]
#            UpdatePlayerBillboard(bID, bName, bName2, jobBType, bType2, value1, value2, cmpValue, autoSort, cmpValue2, **kwargs)
    return
def __CheckFightPowerCanUpdate(curPlayer, key, fightPower, isForceUpdate=False, isCheckRule=True, key2=None):
@@ -252,16 +192,6 @@
    UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_TrialTower, passLV) 
    return
def UpdateTJGBillboard(curPlayer, minuteExp):
    ##脱机效率榜
    if not minuteExp:
        return
    expPoint = minuteExp / ChConfig.Def_PerPointValue
    exp = minuteExp % ChConfig.Def_PerPointValue
    UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_OffLineEfficient, expPoint, exp)
    return
def UpdateRealmBillboard(curPlayer):
    ##境界榜
    if not curPlayer.GetOfficialRank():
@@ -269,54 +199,264 @@
    UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_Realm, curPlayer.GetOfficialRank())
    return
###################################### 以下代码暂时没用,修改时再整合 ################################################
##玩家登录排行处理
# @param curPlayer 玩家实例
# @return
def BillboardOnLogin(curPlayer):
    # 上线默认同步排行榜
    UpdatePlayerBillboardOnLeaveServer(curPlayer) #排行榜已实时更新,故上线不再同步
    return
## 更新当前镖车信息
#  @param playerID: 玩家ID
#  @param playerName: 玩家名字
#  @param playerOpInfo: 玩家平台信息
#  @param playerLV: 玩家等级
#  @param truckLV: 镖车等级
#  @param truckMapID: 镖车所在地图ID
#  @return:
def UpdateBillboardPlayerTruck(playerID, playerName, playerOpInfo, playerLV, truckLV, truckMapID):
def __CanPlayerBillboardComm(curPlayer):
    ## 玩家可否上榜通用检查
    if not GameWorld.IsNormalPlayer(curPlayer):
        return False
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Billboard):
        GameWorld.DebugLog("排行榜未开启,无法上榜!curLV=%s" % (curPlayer.GetLV()), curPlayer.GetPlayerID())
        return False
    
    #当truckMapID为0时表示在排行在删除该镖车的记录
    return True
def UpdatePlayerBillboard(curPlayer, bType, cmpValue, cmpValue2=0, cmpValue3=0, value1=0, value2=0, autoSort=False, **kwargs):
    ## 更新玩家排行榜
    
    #[玩家ID, 玩家名字, 玩家等级, 镖车等级, 镖车位置]
    cmdList = [playerID, playerName, playerOpInfo, playerLV, truckLV, truckMapID]
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "UpdateBillboardPlayerTruck",
                                                              '%s' % (cmdList), len(str(cmdList)))
    return
    #if not cmpValue and not cmpValue2 and not cmpValue3:
    #    return
    
##更新玩家充值排行榜
# @param curPlayer 玩家实例
# @return 任务实例
# @remarks
def UpdateTotalRechargeBillboard(curPlayer):
#    if GameWorld.IsGM(curPlayer):
#        #GM不上榜
#        return
    totalChangeCoinPoint = curPlayer.GetChangeCoinPointTotal()
    #排行榜需要数据[玩家ID, 玩家名字, 玩家职业, 玩家等级]
    if not __CanPlayerBillboardComm(curPlayer):
        return
    playerJob = GetBillboardJob(curPlayer)
    playerID = curPlayer.GetID()
    playerName = curPlayer.GetName()
    playerOpInfo = curPlayer.GetOperateInfo()
    playerJob = curPlayer.GetJob()
    playerLV = curPlayer.GetLV()
    sendMsg = '%s' % ([playerID, playerName, playerOpInfo, playerJob, playerLV, totalChangeCoinPoint])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'UpdateTotalRechargeBillboard', \
            sendMsg, len(sendMsg))
    playerOpInfo = GetBillboardOperateInfo(curPlayer)
    kwargs["value3"] = curPlayer.GetFace()
    kwargs["value4"] = curPlayer.GetFacePic()
    if bType in ShareDefine.BTValue1_OfficialRankList:
        value1 = curPlayer.GetOfficialRank()
    groupValue1 = 0
    UpdateBillboard(bType, groupValue1, playerID, playerName, playerOpInfo, playerJob, value1, value2,
                    cmpValue, cmpValue2, cmpValue3, autoSort=autoSort, **kwargs)
    return
def UpdateBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,
                    cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, autoSort=True, **kwargs):
    ''' 更新跨服排行榜
    @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 GameWorld.IsCrossServer():
        if billboardType not in ShareDefine.CrossBillboardTypeList:
            return
    else:
        if billboardType not in ShareDefine.BillboardTypeList:
            return
    if not dataID:
        return
    billboardMgr = DBDataMgr.GetBillboardMgr()
    billboardObj = billboardMgr.GetBillboard(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 = billboardObj.AddNewBillboardData()
            if not billboardData:
                return
    cmpValueChange = isNewData or billboardData.GetCmpValue() != cmpValue or billboardData.GetCmpValue2() != cmpValue2 \
        or (cmpValue3 and billboardData.GetCmpValue3() != cmpValue3)
    # 没设置值默认为时间time,先上榜的排前面
    if cmpValue3 == 0:
        # 时间权值仅在比较值变更的情况下才更新, 防止其他附属值更新时导致比较值相同的玩家名次间会变动的问题
        if cmpValueChange:
            calcTime = GameWorld.ChangeTimeStrToNum("2090-01-01 00:00:00")
            cmpValue3 = max(0, calcTime - int(time.time())) # 比较值3如果没指定值则默认存当前更新的time
        else:
            cmpValue3 = billboardData.GetCmpValue3()
    # 更新所有值
    billboardData.SetType(billboardType)
    billboardData.SetGroupValue1(groupValue1)
    billboardData.SetGroupValue2(groupValue2)
    billboardData.SetID(dataID)
    billboardData.SetID2(id2)
    billboardData.SetName1(name1)
    billboardData.SetName2(name2)
    billboardData.SetType2(type2)
    billboardData.SetValue1(value1)
    billboardData.SetValue2(value2)
    billboardData.SetValue3(kwargs.get("value3", 0))
    billboardData.SetValue4(kwargs.get("value4", 0))
    billboardData.SetValue5(kwargs.get("value5", 0))
    billboardData.SetValue6(kwargs.get("value6", 0))
    billboardData.SetValue7(kwargs.get("value7", 0))
    billboardData.SetValue8(kwargs.get("value8", 0))
    billboardData.SetUserData(kwargs.get("userData", ""))
    billboardData.SetCmpValue(cmpValue)
    billboardData.SetCmpValue2(cmpValue2)
    billboardData.SetCmpValue3(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,%s"
                       % (billboardType, groupValue1, groupValue2, dataID, isNewData, cmpValueChange,
                          type2, value1, value2, cmpValue, cmpValue2, cmpValue3, kwargs), dataID)
    if not autoSort:
        if isNewData or cmpValueChange:
            billboardObj.SetSortDelay()
    else:
        billboardObj.SortData()
    return True
def __CmpLastBillboardData(cmpValue, cmpValue2, cmpValue3, billboardObj):
    ## 比较是否超过最后一名
    # @return: 超过则返回最后一名数据实例,否则返回None
    if not billboardObj.GetCount():
        return
    lastBillBoardData = billboardObj.At(billboardObj.GetCount() - 1)
    if cmpValue < lastBillBoardData.GetCmpValue():
        #无法上榜
        return
    elif cmpValue == lastBillBoardData.GetCmpValue():
        if cmpValue2 < lastBillBoardData.GetCmpValue2():
            return
        elif cmpValue2 == lastBillBoardData.GetCmpValue2():
            if cmpValue3 <= lastBillBoardData.GetCmpValue3():
                return
    return lastBillBoardData
def UpdatePlayerCrossBillboard(curPlayer, bType, groupValue1, cmpValue, cmpValue2=0, cmpValue3=0, value1=0, value2=0,
                               groupValue2=0, **kwargs):
    ## 在本服直接更新玩家跨服排行榜,发送到跨服,之后扩展
    return
#// A1 30 查看榜单 #tagCMViewBillboard
#
#struct    tagCMViewBillboard
#{
#    tagHead        Head;
#    BYTE        Type;        //榜单类型
#    DWORD        GroupValue1;    //分组值1
#    DWORD        GroupValue2;    //分组值2,与分组值1组合归为同组榜单数据
#    WORD        StartIndex;    //查看的起始名次索引, 默认0
#    BYTE        ViewCnt;        //查看条数,默认20,单次最大不超过100
#    DWORD        ViewID;        //附带查看指定ID所在名次前后数据,如玩家ID、家族ID等
#};
def OnViewBillboard(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    billboardType, groupValue1, groupValue2 = clientData.Type, clientData.GroupValue1, clientData.GroupValue2
    startIndex = clientData.StartIndex
    viewCnt = clientData.ViewCnt
    viewID = clientData.ViewID
    if billboardType in ShareDefine.CrossBillboardTypeList:
        # 跨服榜单直接查跨服服务器,待扩展
        return
    clientPack = GetPack_ViewBillboardRet(billboardType, groupValue1, groupValue2, startIndex, viewCnt, viewID)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
def GetPack_ViewBillboardRet(bbType, groupValue1, groupValue2, startIndex=0, viewCnt=20, viewID=0):
    ## 获取查看榜单返回信息封包,本服跨服通用
    billboardMgr = DBDataMgr.GetBillboardMgr()
    billboardObj = billboardMgr.GetBillboard(bbType, groupValue1, groupValue2)
    billboardObj.SortDelayDo()
    idOrderDict = billboardObj.GetIDOrderDict()
    count = billboardObj.GetCount()
    maxIndex = count - 1
    startIndex = max(min(startIndex, maxIndex), 0)
    viewCnt = 20 if not viewCnt else min(viewCnt, 100) # 默认20,最多100
    endIndex = min(startIndex + viewCnt - 1, maxIndex)
    viewRange = [] if not count else range(startIndex, endIndex + 1)
    viewIDRange = []
    # 查看viewID前后名次
    if viewID:
        viewBFCnt = 3 # 查看ViewID返回前后数据条数,一般设置为奇数
        viewIDIndex = billboardObj.IndexOfByID(viewID)
        if viewIDIndex != -1:
            # 前x后x
            viewIDStartIndex = max(0, viewIDIndex - viewBFCnt / 2)
            viewIDEndIndex = min(viewIDIndex + viewBFCnt / 2, maxIndex)
            viewIDRange = range(viewIDStartIndex, viewIDEndIndex + 1)
    clientPack = ChPyNetSendPack.tagMCViewBillboardRet()
    clientPack.Type = bbType
    clientPack.GroupValue1 = groupValue1
    clientPack.GroupValue2 = groupValue2
    clientPack.DataTotal = count
    clientPack.PageDataList = []
    for index in viewRange:
        billboardData = billboardObj.At(index)
        viewData = ChPyNetSendPack.tagMCViewBillboardData()
        viewData.Index = index
        viewData.Rank = idOrderDict.get(billboardData.GetID(), 0)
        viewData.ID = billboardData.GetID()
        viewData.ID2 = billboardData.GetID2()
        viewData.Name1 = billboardData.GetName1()
        viewData.Name2 = billboardData.GetName2()
        viewData.Type2 = billboardData.GetType2()
        viewData.Value1 = billboardData.GetValue1()
        viewData.Value2 = billboardData.GetValue2()
        viewData.Value3 = billboardData.GetValue3()
        viewData.Value4 = billboardData.GetValue4()
        viewData.Value5 = billboardData.GetValue5()
        viewData.Value6 = billboardData.GetValue6()
        viewData.Value7 = billboardData.GetValue7()
        viewData.Value8 = billboardData.GetValue8()
        viewData.CmpValue = billboardData.GetCmpValue()
        viewData.CmpValue2 = billboardData.GetCmpValue2()
        viewData.CmpValue3 = billboardData.GetCmpValue3()
        viewData.UserData = billboardData.GetUserData()
        viewData.DataLen = len(viewData.UserData)
        clientPack.PageDataList.append(viewData)
    clientPack.PageDataCnt = len(clientPack.PageDataList)
    clientPack.ViewID = viewID
    clientPack.ViewIDDataList = []
    for index in viewIDRange:
        billboardData = billboardObj.At(index)
        viewData = ChPyNetSendPack.tagMCViewBillboardData()
        viewData.Index = index
        viewData.Rank = idOrderDict.get(billboardData.GetID(), 0)
        viewData.ID = billboardData.GetID()
        viewData.ID2 = billboardData.GetID2()
        viewData.Name1 = billboardData.GetName1()
        viewData.Name2 = billboardData.GetName2()
        viewData.Type2 = billboardData.GetType2()
        viewData.Value1 = billboardData.GetValue1()
        viewData.Value2 = billboardData.GetValue2()
        viewData.Value3 = billboardData.GetValue3()
        viewData.Value4 = billboardData.GetValue4()
        viewData.Value5 = billboardData.GetValue5()
        viewData.Value6 = billboardData.GetValue6()
        viewData.Value7 = billboardData.GetValue7()
        viewData.Value8 = billboardData.GetValue8()
        viewData.CmpValue = billboardData.GetCmpValue()
        viewData.CmpValue2 = billboardData.GetCmpValue2()
        viewData.CmpValue3 = billboardData.GetCmpValue3()
        viewData.UserData = billboardData.GetUserData()
        viewData.DataLen = len(viewData.UserData)
        clientPack.ViewIDDataList.append(viewData)
    clientPack.ViewIDDataCnt = len(clientPack.ViewIDDataList)
    return clientPack
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -124,11 +124,11 @@
import PlayerAssist
import PlayerArena
import PyGameData
import PlayerTJG
import PlayerGuaji
import PlayerXiangong
import PlayerFuncTeam
import PlayerMineArea
import PlayerBillboard
import PlayerMail
import datetime
@@ -166,6 +166,8 @@
        PlayerOnDayEx(curPlayer)
    
    DoLogic_OnDayEx(tick)
    PlayerBillboard.OnDay()
    return
def DoLogic_OnDayEx(tick):
@@ -426,7 +428,6 @@
        #特殊时间点过天的,一般是游戏功能,此时立即同步一次跨服玩家数据
        CrossPlayerData.SendMergePlayerDataNow(curPlayer)
        
    #PlayerTJG.TJGOnDay(curPlayer, onEventType)
    # 以下为支持两种重置模式切换配置的
    FBCommon.FBOnDay(curPlayer, onEventType)
    
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py
@@ -718,7 +718,7 @@
    totalExp = exp2 * ChConfig.Def_PerPointValue + exp1
    aveMinuteExp = int(totalExp * 1.0 / max(1, times / 60)) # 平均每分钟经验
    GameWorld.DebugLog('    脱机效率榜  aveMinuteExp=%s, totalExp=%s,times=%s' % (aveMinuteExp, totalExp, times))
    PlayerBillboard.UpdateTJGBillboard(curPlayer, aveMinuteExp)
    #PlayerBillboard.UpdateTJGBillboard(curPlayer, aveMinuteExp)
    
    sendPack = ChPyNetSendPack.tagMCTJGInfo()
    sendPack.Clear()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTruck.py
@@ -229,8 +229,8 @@
    DataRecordPack.DR_Truck(curPlayer, "Star", {"LV":truckLv})
    
    #更新镖车进排行榜
    PlayerBillboard.UpdateBillboardPlayerTruck(curPlayer.GetPlayerID(), curPlayer.GetName(), curPlayer.GetOperateInfo(),
                                               curPlayer.GetLV(), truckLv, curPlayer.GetMapID())
    #PlayerBillboard.UpdateBillboardPlayerTruck(curPlayer.GetPlayerID(), curPlayer.GetName(), curPlayer.GetOperateInfo(),
    #                                           curPlayer.GetLV(), truckLv, curPlayer.GetMapID())
    
    #拉镖活跃度
    #PlayerActivity.AddActivityFinishCnt(curPlayer, ShareDefine.ActivityNum_Truck)
@@ -411,7 +411,7 @@
        curTruck.SetIsDisappear(1)
        
        ##删除排行榜上的镖车信息
        PlayerBillboard.UpdateBillboardPlayerTruck(curTruck.GetOwnerID(), "", "", "", "", 0)
        #PlayerBillboard.UpdateBillboardPlayerTruck(curTruck.GetOwnerID(), "", "", "", "", 0)
            
#        curPlayer = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, curTruck)
#
@@ -519,7 +519,7 @@
    curTruck.Disappear()
    
    #删除排行榜上的镖车信息
    PlayerBillboard.UpdateBillboardPlayerTruck(curPlayer.GetID(), "", "", "", "", 0)
    #PlayerBillboard.UpdateBillboardPlayerTruck(curPlayer.GetID(), "", "", "", "", 0)
    
    GameWorld.Log("删除玩家骠车" , curPlayer.GetPlayerID())
    #GameWorld.Log("通知GameServer骠车消失!")
@@ -796,7 +796,7 @@
    truckOwnerID = curTruck.GetOwnerID()
    
    #已经被打劫下榜
    PlayerBillboard.UpdateBillboardPlayerTruck(truckOwnerID, "", "", "", "", 0)
    #PlayerBillboard.UpdateBillboardPlayerTruck(truckOwnerID, "", "", "", "", 0)
    #-----------------------
    
    #获取镖车主人
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -944,6 +944,8 @@
Def_CBT_FamilyGCZRoundHurt, # 仙盟攻城战 - 本轮分组仙盟伤害榜  169 (zoneID, batType*100+groupNum)
) = range(150, 169 + 1)
BillboardTypeAllList = BillboardTypeList + CrossBillboardTypeList
#职业对应战力排行榜类型
JobFightPowerBillboardDict = {
                              PlayerJob_Warrior:Def_BT_FightPower_Warrior,