hxp
2024-03-07 3d3a72a7c8482ec217d936c8fcee3cea07cfb785
10130 【后端】福地争夺资源功能

# Conflicts:
# ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCoin.py
18个文件已修改
5个文件已添加
3985 ■■■■■ 已修改文件
PySysDB/PySysDBG.h 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py 533 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/MineArea.py 228 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldMineArea.py 1320 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py 301 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 533 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MineArea.py 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMineArea.py 316 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_MineArea.py 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBG.h
@@ -1202,6 +1202,21 @@
    BYTE        UnSuitRate;    //单件非套装加成概率
};
//福地物品表
struct tagMineAreaItem
{
    BYTE        _MineID;    //矿物ID
    WORD        LimitLV;    //解锁等级
    DWORD        ItemID;        //物品ID
    BYTE        ItemLV;        //物品等级
    DWORD        ItemCount;    //物品个数
    float        ItemWeight;    //物品总重量
    DWORD        RefreshWeightSys;    //系统刷新权重
    DWORD        RefreshWeight;    //常规刷新权重
    DWORD        RefreshWeightSuper;    //超级刷新权重
};
//仙盟联赛排名奖励表
struct tagFamilyWarRankAward
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
@@ -541,3 +541,18 @@
PacketSubCMD_1=0x07
PacketCallFunc_1=OnVoiceChat
[GameWorldMineArea]
ScriptName = GameWorldLogic\GameWorldMineArea.py
Writer = hxp
Releaser = hxp
RegType = 0
RegisterPackCount = 2
PacketCMD_1=0xB0
PacketSubCMD_1=0x33
PacketCallFunc_1=OnMineAreaView
PacketCMD_2=0xB0
PacketSubCMD_2=0x34
PacketCallFunc_2=OnMineAreaAwardGet
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -2117,6 +2117,110 @@
#------------------------------------------------------
# B0 34 福地请求结算奖励 #tagCGMineAreaAwardGet
class  tagCGMineAreaAwardGet(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        self.SubCmd = 0x34
        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 = 0xB0
        self.SubCmd = 0x34
        return
    def GetLength(self):
        return sizeof(tagCGMineAreaAwardGet)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 34 福地请求结算奖励 //tagCGMineAreaAwardGet:
                                Cmd:%s,
                                SubCmd:%s
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd
                                )
        return DumpString
m_NAtagCGMineAreaAwardGet=tagCGMineAreaAwardGet()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGMineAreaAwardGet.Cmd,m_NAtagCGMineAreaAwardGet.SubCmd))] = m_NAtagCGMineAreaAwardGet
#------------------------------------------------------
# B0 33 福地查看 #tagCGMineAreaView
class  tagCGMineAreaView(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("QueryType", c_ubyte),    # 查询同步类型:0-后端主动同步;1-查看指定福地;2-查看道友福地列表;3-查看周围随机福地列表;4-退出他人福地;
                  ("QueryValue", c_int),    # 查询值,类型1时-发送目标玩家ID;3时-发送是否重新随机
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        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 = 0xB0
        self.SubCmd = 0x33
        self.QueryType = 0
        self.QueryValue = 0
        return
    def GetLength(self):
        return sizeof(tagCGMineAreaView)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 33 福地查看 //tagCGMineAreaView:
                                Cmd:%s,
                                SubCmd:%s,
                                QueryType:%d,
                                QueryValue:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.QueryType,
                                self.QueryValue
                                )
        return DumpString
m_NAtagCGMineAreaView=tagCGMineAreaView()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGMineAreaView.Cmd,m_NAtagCGMineAreaView.SubCmd))] = m_NAtagCGMineAreaView
#------------------------------------------------------
#B0 25 请求家族悬赏任务完成情况 #tagQueryFamilyArrestOverState
class  tagQueryFamilyArrestOverState(Structure):
@@ -17341,6 +17445,170 @@
#------------------------------------------------------
# B0 30 福地物品拉 #tagCMMineItemPull
class  tagCMMineItemPull(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("PlayerID", c_int),    # 福地所属玩家ID,0默认自己
                  ("ItemIndex", c_ubyte),    # 物品所在位置索引0~n
                  ("WorkerCount", c_ubyte),    # 上工人人数
                  ("IsPreview", c_ubyte),    # 是否预览;0-直接拉,1-预览大概时间
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        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 = 0xB0
        self.SubCmd = 0x30
        self.PlayerID = 0
        self.ItemIndex = 0
        self.WorkerCount = 0
        self.IsPreview = 0
        return
    def GetLength(self):
        return sizeof(tagCMMineItemPull)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 30 福地物品拉 //tagCMMineItemPull:
                                Cmd:%s,
                                SubCmd:%s,
                                PlayerID:%d,
                                ItemIndex:%d,
                                WorkerCount:%d,
                                IsPreview:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.PlayerID,
                                self.ItemIndex,
                                self.WorkerCount,
                                self.IsPreview
                                )
        return DumpString
m_NAtagCMMineItemPull=tagCMMineItemPull()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMMineItemPull.Cmd,m_NAtagCMMineItemPull.SubCmd))] = m_NAtagCMMineItemPull
#------------------------------------------------------
# B0 31 福地物品刷新 #tagCMMineItemRefresh
class  tagCMMineItemRefresh(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("IsSuper", c_ubyte),    # 是否超级刷新
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        self.SubCmd = 0x31
        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 = 0xB0
        self.SubCmd = 0x31
        self.IsSuper = 0
        return
    def GetLength(self):
        return sizeof(tagCMMineItemRefresh)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 31 福地物品刷新 //tagCMMineItemRefresh:
                                Cmd:%s,
                                SubCmd:%s,
                                IsSuper:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.IsSuper
                                )
        return DumpString
m_NAtagCMMineItemRefresh=tagCMMineItemRefresh()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMMineItemRefresh.Cmd,m_NAtagCMMineItemRefresh.SubCmd))] = m_NAtagCMMineItemRefresh
#------------------------------------------------------
# B0 32 福地工人雇佣 #tagCMMineWorkerEmploy
class  tagCMMineWorkerEmploy(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        self.SubCmd = 0x32
        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 = 0xB0
        self.SubCmd = 0x32
        return
    def GetLength(self):
        return sizeof(tagCMMineWorkerEmploy)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 32 福地工人雇佣 //tagCMMineWorkerEmploy:
                                Cmd:%s,
                                SubCmd:%s
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd
                                )
        return DumpString
m_NAtagCMMineWorkerEmploy=tagCMMineWorkerEmploy()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMMineWorkerEmploy.Cmd,m_NAtagCMMineWorkerEmploy.SubCmd))] = m_NAtagCMMineWorkerEmploy
#------------------------------------------------------
#B0 26 请求家族悬赏奖励领取情况 #tagQueryFamilyArrestAwardReceiveState
class  tagQueryFamilyArrestAwardReceiveState(Structure):
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -7722,6 +7722,424 @@
#------------------------------------------------------
# B0 34 福地结算奖励信息 #tagGCMineAreaAwardInfo
class  tagGCMineAreaAwardInfo(Structure):
    Head = tagHead()
    AwardType = 0    #(BYTE AwardType)// 0-通知有奖励,前端下次进入福地可请求进行结算;1-结算奖励结果通知
    AwardLen = 0    #(BYTE AwardLen)
    AwardInfo = ""    #(String AwardInfo)//奖励信息 [物品ID,个数,是否拍品], ...]
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x34
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.AwardType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.AwardLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.AwardInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.AwardLen)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x34
        self.AwardType = 0
        self.AwardLen = 0
        self.AwardInfo = ""
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 1
        length += len(self.AwardInfo)
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.AwardType)
        data = CommFunc.WriteBYTE(data, self.AwardLen)
        data = CommFunc.WriteString(data, self.AwardLen, self.AwardInfo)
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                AwardType:%d,
                                AwardLen:%d,
                                AwardInfo:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.AwardType,
                                self.AwardLen,
                                self.AwardInfo
                                )
        return DumpString
m_NAtagGCMineAreaAwardInfo=tagGCMineAreaAwardInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCMineAreaAwardInfo.Head.Cmd,m_NAtagGCMineAreaAwardInfo.Head.SubCmd))] = m_NAtagGCMineAreaAwardInfo
#------------------------------------------------------
# B0 33 福地详细信息 #tagGCMineAreaInfo
class  tagGCMineItem(Structure):
    Index = 0    #(BYTE Index)// 矿物所在福地位置索引,0~n
    MineID = 0    #(WORD MineID)// 矿物ID,对应福地采集表中ID,0代表该索引位置没有矿物
    MineType = 0    #(BYTE MineType)// 矿物类型:0-常规;1-超级
    UpdTime = 0    #(DWORD UpdTime)// 最后一次更新时间戳
    PosLen = 0    #(BYTE PosLen)
    Position = ""    #(String Position)// 最后一次更新时所在位置百分比,0~100,支持小数,下0上100,可认为分为100格,速度为 x格/秒
    SpeedLen = 0    #(BYTE SpeedLen)
    MoveSpeed = ""    #(String MoveSpeed)// 移动速度,x格/秒,支持小数
    EndTime = 0    #(DWORD EndTime)// 拉取结束时间戳
    WorkerCount = 0    #(BYTE WorkerCount)// 工人个数,为0时代表福地玩家没有使用工人拉回
    RobPlayerID = 0    #(DWORD RobPlayerID)// 抢夺玩家ID,为0时代表没人抢夺
    RobWorkerCount = 0    #(BYTE RobWorkerCount)// 抢夺工人个数
    RobPlayerName = ""    #(char RobPlayerName[33])
    RobFace = 0    #(DWORD RobFace)
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.Index,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.MineID,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.MineType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.UpdTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.PosLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.Position,_pos = CommFunc.ReadString(_lpData, _pos,self.PosLen)
        self.SpeedLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.MoveSpeed,_pos = CommFunc.ReadString(_lpData, _pos,self.SpeedLen)
        self.EndTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.WorkerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.RobPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.RobWorkerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.RobPlayerName,_pos = CommFunc.ReadString(_lpData, _pos,33)
        self.RobFace,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        return _pos
    def Clear(self):
        self.Index = 0
        self.MineID = 0
        self.MineType = 0
        self.UpdTime = 0
        self.PosLen = 0
        self.Position = ""
        self.SpeedLen = 0
        self.MoveSpeed = ""
        self.EndTime = 0
        self.WorkerCount = 0
        self.RobPlayerID = 0
        self.RobWorkerCount = 0
        self.RobPlayerName = ""
        self.RobFace = 0
        return
    def GetLength(self):
        length = 0
        length += 1
        length += 2
        length += 1
        length += 4
        length += 1
        length += len(self.Position)
        length += 1
        length += len(self.MoveSpeed)
        length += 4
        length += 1
        length += 4
        length += 1
        length += 33
        length += 4
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteBYTE(data, self.Index)
        data = CommFunc.WriteWORD(data, self.MineID)
        data = CommFunc.WriteBYTE(data, self.MineType)
        data = CommFunc.WriteDWORD(data, self.UpdTime)
        data = CommFunc.WriteBYTE(data, self.PosLen)
        data = CommFunc.WriteString(data, self.PosLen, self.Position)
        data = CommFunc.WriteBYTE(data, self.SpeedLen)
        data = CommFunc.WriteString(data, self.SpeedLen, self.MoveSpeed)
        data = CommFunc.WriteDWORD(data, self.EndTime)
        data = CommFunc.WriteBYTE(data, self.WorkerCount)
        data = CommFunc.WriteDWORD(data, self.RobPlayerID)
        data = CommFunc.WriteBYTE(data, self.RobWorkerCount)
        data = CommFunc.WriteString(data, 33, self.RobPlayerName)
        data = CommFunc.WriteDWORD(data, self.RobFace)
        return data
    def OutputString(self):
        DumpString = '''
                                Index:%d,
                                MineID:%d,
                                MineType:%d,
                                UpdTime:%d,
                                PosLen:%d,
                                Position:%s,
                                SpeedLen:%d,
                                MoveSpeed:%s,
                                EndTime:%d,
                                WorkerCount:%d,
                                RobPlayerID:%d,
                                RobWorkerCount:%d,
                                RobPlayerName:%s,
                                RobFace:%d
                                '''\
                                %(
                                self.Index,
                                self.MineID,
                                self.MineType,
                                self.UpdTime,
                                self.PosLen,
                                self.Position,
                                self.SpeedLen,
                                self.MoveSpeed,
                                self.EndTime,
                                self.WorkerCount,
                                self.RobPlayerID,
                                self.RobWorkerCount,
                                self.RobPlayerName,
                                self.RobFace
                                )
        return DumpString
class  tagGCMineArea(Structure):
    PlayerID = 0    #(DWORD PlayerID)// 福地所属玩家ID,可能是自己或其他玩家ID,当ID小于10000时为假人
    PlayerName = ""    #(char PlayerName[33])// 可能为空,如自己或假人
    Face = 0    #(DWORD Face)
    MineCount = 0    #(BYTE MineCount)
    MineItemList = list()    #(vector<tagGCMineItem> MineItemList)// 矿物列表
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.PlayerName,_pos = CommFunc.ReadString(_lpData, _pos,33)
        self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.MineCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.MineCount):
            temMineItemList = tagGCMineItem()
            _pos = temMineItemList.ReadData(_lpData, _pos)
            self.MineItemList.append(temMineItemList)
        return _pos
    def Clear(self):
        self.PlayerID = 0
        self.PlayerName = ""
        self.Face = 0
        self.MineCount = 0
        self.MineItemList = list()
        return
    def GetLength(self):
        length = 0
        length += 4
        length += 33
        length += 4
        length += 1
        for i in range(self.MineCount):
            length += self.MineItemList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteDWORD(data, self.PlayerID)
        data = CommFunc.WriteString(data, 33, self.PlayerName)
        data = CommFunc.WriteDWORD(data, self.Face)
        data = CommFunc.WriteBYTE(data, self.MineCount)
        for i in range(self.MineCount):
            data = CommFunc.WriteString(data, self.MineItemList[i].GetLength(), self.MineItemList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                PlayerID:%d,
                                PlayerName:%s,
                                Face:%d,
                                MineCount:%d,
                                MineItemList:%s
                                '''\
                                %(
                                self.PlayerID,
                                self.PlayerName,
                                self.Face,
                                self.MineCount,
                                "..."
                                )
        return DumpString
class  tagGCMineAreaInfo(Structure):
    Head = tagHead()
    QueryType = 0    #(BYTE QueryType)// 查询同步类型:0-后端主动同步;1-查看指定福地;2-查看道友福地列表;3-查看周围随机福地列表
    QueryValue = 0    #(DWORD QueryValue)// 查询值,类型1时-发送目标玩家ID;3时-发送是否重新随机
    AreaCount = 0    #(BYTE AreaCount)
    AreaList = list()    #(vector<tagGCMineArea> AreaList)// 福地列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x33
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.QueryType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.QueryValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.AreaCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.AreaCount):
            temAreaList = tagGCMineArea()
            _pos = temAreaList.ReadData(_lpData, _pos)
            self.AreaList.append(temAreaList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x33
        self.QueryType = 0
        self.QueryValue = 0
        self.AreaCount = 0
        self.AreaList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 4
        length += 1
        for i in range(self.AreaCount):
            length += self.AreaList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.QueryType)
        data = CommFunc.WriteDWORD(data, self.QueryValue)
        data = CommFunc.WriteBYTE(data, self.AreaCount)
        for i in range(self.AreaCount):
            data = CommFunc.WriteString(data, self.AreaList[i].GetLength(), self.AreaList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                QueryType:%d,
                                QueryValue:%d,
                                AreaCount:%d,
                                AreaList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.QueryType,
                                self.QueryValue,
                                self.AreaCount,
                                "..."
                                )
        return DumpString
m_NAtagGCMineAreaInfo=tagGCMineAreaInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCMineAreaInfo.Head.Cmd,m_NAtagGCMineAreaInfo.Head.SubCmd))] = m_NAtagGCMineAreaInfo
#------------------------------------------------------
# B0 32 福地物品拉预览结果 #tagGCMineItemPullPreviewRet
class  tagGCMineItemPullPreviewRet(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("PlayerID", c_int),    # 福地所属玩家ID,0默认自己
                  ("ItemIndex", c_ubyte),    # 物品所在位置索引0~n
                  ("WorkerCount", c_ubyte),    # 上工人人数
                  ("NeedSeconds", c_int),    # 预计需要时间,秒
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        self.SubCmd = 0x32
        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 = 0xB0
        self.SubCmd = 0x32
        self.PlayerID = 0
        self.ItemIndex = 0
        self.WorkerCount = 0
        self.NeedSeconds = 0
        return
    def GetLength(self):
        return sizeof(tagGCMineItemPullPreviewRet)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 32 福地物品拉预览结果 //tagGCMineItemPullPreviewRet:
                                Cmd:%s,
                                SubCmd:%s,
                                PlayerID:%d,
                                ItemIndex:%d,
                                WorkerCount:%d,
                                NeedSeconds:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.PlayerID,
                                self.ItemIndex,
                                self.WorkerCount,
                                self.NeedSeconds
                                )
        return DumpString
m_NAtagGCMineItemPullPreviewRet=tagGCMineItemPullPreviewRet()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCMineItemPullPreviewRet.Cmd,m_NAtagGCMineItemPullPreviewRet.SubCmd))] = m_NAtagGCMineItemPullPreviewRet
#------------------------------------------------------
# B0 04 使用协助感谢礼盒预览 #tagGCUseAssistThanksGiftPreview
class  tagGCAssistPlayerInfo(Structure):
@@ -44010,6 +44428,121 @@
#------------------------------------------------------
# B0 30 玩家福地相关信息 #tagMCPlayerMineAreaInfo
class  tagMCPlayerMineAreaInfo(Structure):
    Head = tagHead()
    WorkerCount = 0    #(BYTE WorkerCount)// 已雇佣工人数
    EnergyUsed = 0    #(WORD EnergyUsed)// 今日已消耗体力
    RefreshCount = 0    #(DWORD RefreshCount)// 今日福地刷新物品次数 - 普通刷新
    RefreshCountSuper = 0    #(BYTE RefreshCountSuper)// 今日福地刷新物品次数 - 超级刷新
    TreasureCount = 0    #(BYTE TreasureCount)// 聚宝盆类型个数,对应类型 0~n
    TreasureState = list()    #(vector<BYTE> TreasureState)// 聚宝盆是否已激活列表,[类型0是否已激活, ...]
    TreasureAward = list()    #(vector<BYTE> TreasureAward)// 聚宝盆奖励是否已领取列表,[类型0是否已领取, ...]
    TreasureProgress = list()    #(vector<BYTE> TreasureProgress)// 聚宝盆进度值列表,[类型0进度值, ...],满进度100
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x30
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.WorkerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.EnergyUsed,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.RefreshCount,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.RefreshCountSuper,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.TreasureCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.TreasureCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.TreasureState.append(value)
        for i in range(self.TreasureCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.TreasureAward.append(value)
        for i in range(self.TreasureCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.TreasureProgress.append(value)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x30
        self.WorkerCount = 0
        self.EnergyUsed = 0
        self.RefreshCount = 0
        self.RefreshCountSuper = 0
        self.TreasureCount = 0
        self.TreasureState = list()
        self.TreasureAward = list()
        self.TreasureProgress = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 2
        length += 4
        length += 1
        length += 1
        length += 1 * self.TreasureCount
        length += 1 * self.TreasureCount
        length += 1 * self.TreasureCount
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.WorkerCount)
        data = CommFunc.WriteWORD(data, self.EnergyUsed)
        data = CommFunc.WriteDWORD(data, self.RefreshCount)
        data = CommFunc.WriteBYTE(data, self.RefreshCountSuper)
        data = CommFunc.WriteBYTE(data, self.TreasureCount)
        for i in range(self.TreasureCount):
            data = CommFunc.WriteBYTE(data, self.TreasureState[i])
        for i in range(self.TreasureCount):
            data = CommFunc.WriteBYTE(data, self.TreasureAward[i])
        for i in range(self.TreasureCount):
            data = CommFunc.WriteBYTE(data, self.TreasureProgress[i])
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                WorkerCount:%d,
                                EnergyUsed:%d,
                                RefreshCount:%d,
                                RefreshCountSuper:%d,
                                TreasureCount:%d,
                                TreasureState:%s,
                                TreasureAward:%s,
                                TreasureProgress:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.WorkerCount,
                                self.EnergyUsed,
                                self.RefreshCount,
                                self.RefreshCountSuper,
                                self.TreasureCount,
                                "...",
                                "...",
                                "..."
                                )
        return DumpString
m_NAtagMCPlayerMineAreaInfo=tagMCPlayerMineAreaInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCPlayerMineAreaInfo.Head.Cmd,m_NAtagMCPlayerMineAreaInfo.Head.SubCmd))] = m_NAtagMCPlayerMineAreaInfo
#------------------------------------------------------
# B0 07 今日协助活跃令信息 #tagMCTodayAssistMoneyInfo
class  tagMCTodayAssistMoneyInfo(Structure):
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/MineArea.py
New file
@@ -0,0 +1,228 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GM.Commands.MineArea
#
# @todo:福地
# @author hxp
# @date 2024-03-07
# @version 1.0
#
# 详细描述: 福地
#
#-------------------------------------------------------------------------------
#"""Version = 2024-03-07 19:30"""
#-------------------------------------------------------------------------------
import GameWorld
import PyDataManager
import GameWorldMineArea
import IpyGameDataPY
import time
#逻辑实现
## 执行逻辑
#  @param curPlayer 当前玩家
#  @param gmList [cmdIndex gmAccID msg]
#  @return None
#  @remarks 函数详细说明.
def OnExec(curPlayer, msgList):
    if not msgList:
        GameWorld.DebugAnswer(curPlayer, "以下是GameServer命令")
        GameWorld.DebugAnswer(curPlayer, "随机重新刷新: MineArea item [是否超级 坐标 索引]")
        GameWorld.DebugAnswer(curPlayer, "刷新指定等级: MineArea lv 等级 [坐标 索引]")
        GameWorld.DebugAnswer(curPlayer, "刷新指定物品: MineArea id 矿物ID [坐标 索引]")
        GameWorld.DebugAnswer(curPlayer, "派工人拉物品: MineArea pull 索引 人数 状态")
        GameWorld.DebugAnswer(curPlayer, "[工人玩家ID 福地玩家ID]")
        GameWorld.DebugAnswer(curPlayer, "输出在拉物品: MineArea pulling [玩家ID]")
        GameWorld.DebugAnswer(curPlayer, "输出福地物品: MineArea area [福地玩家ID]")
        GameWorld.DebugAnswer(curPlayer, "清除福地物品: MineArea clear [福地玩家ID,isPop]")
        GameWorld.DebugAnswer(curPlayer, "输出功能数据: MineArea info")
        GameWorld.DebugAnswer(curPlayer, "坐标: 0~100; []内为可选参数")
        GameWorld.DebugAnswer(curPlayer, "玩家ID可以是假人ID: 1~%s" % GameWorldMineArea.Def_FakeAreaCount)
        return
    playerID = curPlayer.GetPlayerID()
    value1 = msgList[0]
    if value1 == "item":
        isSuper = msgList[1] if len(msgList) > 1 else 0
        position = msgList[2] if len(msgList) > 2 else None
        refreshIndexList = [msgList[3]] if len(msgList) > 3 else None
        refreshDict = GameWorldMineArea.__DoMineItemRefresh(playerID, curPlayer, isSuper=isSuper, refreshIndexList=refreshIndexList, setPosition=position)
        __PrintRefreshDict(curPlayer, refreshDict, "超级" if isSuper else "普通")
    # 刷新指定等级
    elif value1 == "lv":
        itemLV = msgList[1] if len(msgList) > 1 else 1
        position = msgList[2] if len(msgList) > 2 else None
        refreshIndexList = [msgList[3]] if len(msgList) > 3 else None
        refreshDict = GameWorldMineArea.__DoMineItemRefresh(playerID, curPlayer, refreshIndexList=refreshIndexList, setPosition=position, setItemLV=itemLV)
        __PrintRefreshDict(curPlayer, refreshDict, "指定等级:%s" % itemLV)
    # 刷新指定物品
    elif value1 == "id":
        mineID = msgList[1] if len(msgList) > 1 else 1
        position = msgList[2] if len(msgList) > 2 else None
        refreshIndexList = [msgList[3]] if len(msgList) > 3 else None
        refreshDict = GameWorldMineArea.__DoMineItemRefresh(playerID, curPlayer, refreshIndexList=refreshIndexList, setPosition=position, setMineID=mineID)
        __PrintRefreshDict(curPlayer, refreshDict, "指定ID:%s" % mineID)
    # 派工人拉物品
    elif value1 == "pull":
        itemIndex = msgList[1] if len(msgList) > 1 else 0
        workerCount = msgList[2] if len(msgList) > 2 else 1
        workerState = msgList[3] if len(msgList) > 3 else 0
        workerID = msgList[4] if len(msgList) > 4 else playerID
        areaPlayerID = msgList[5] if len(msgList) > 5 else playerID
        if not workerID:
            workerID = playerID
        workerPlayer = GameWorld.GetPlayerManager().FindPlayerByID(workerID)
        if not areaPlayerID:
            areaPlayerID = playerID
        workerTotal, isPreview = 999, False
        dataMsg = [areaPlayerID, itemIndex, workerCount, workerState, workerTotal, isPreview]
        GameWorldMineArea.__DoPullItem(workerID, workerPlayer, dataMsg)
    # 输出正在拉的物品
    elif value1 == "pulling":
        pullPlayerID = msgList[1] if len(msgList) > 1 else playerID
        mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
        itemList = mineItemMgr.pullingItemListDict.get(pullPlayerID, [])
        GameWorld.DebugAnswer(curPlayer, "正在拉的物品数: %s %s %s" % (len(itemList), pullPlayerID, GameWorld.ChangeTimeNumToStr(int(time.time()))))
        GameWorld.DebugLog("------ 正在拉的物品 ------ %s" % len(itemList), pullPlayerID)
        for mineItemData in itemList:
            __PrintMineItemLog(curPlayer, mineItemData.PlayerID, mineItemData.Index)
        GameWorld.DebugLog("---------------------", pullPlayerID)
    # 输出福地物品
    elif value1 == "area":
        areaPlayerID = msgList[1] if len(msgList) > 1 else playerID
        GameWorld.DebugAnswer(curPlayer, "福地物品: %s %s" % (areaPlayerID, GameWorld.ChangeTimeNumToStr(int(time.time()))))
        GameWorld.DebugLog("------ 福地物品 ------", areaPlayerID)
        for index in range(IpyGameDataPY.GetFuncCfg("MineAreaBase", 1)):
            __PrintMineItemLog(curPlayer, areaPlayerID, index)
        GameWorld.DebugLog("---------------------", areaPlayerID)
    # 清除福地物品
    elif value1 == "clear":
        areaPlayerID = msgList[1] if len(msgList) > 1 else playerID
        if not areaPlayerID:
            areaPlayerID = playerID
        isPop = msgList[2] if len(msgList) > 2 else 1
        __ClearAreaData(curPlayer, areaPlayerID, isPop)
    # 输出功能数据
    elif value1 == "info":
        __PrintAreaFuncInfo(curPlayer)
    else:
        GameWorld.DebugAnswer(curPlayer, "没有该命令")
    return
def __PrintRefreshDict(curPlayer, refreshDict, mark):
    if not refreshDict:
        GameWorld.DebugAnswer(curPlayer, "没有刷新出新物品")
        return
    GameWorld.DebugAnswer(curPlayer, "刷新福地物品: %s" % mark)
    for index, refreshInfo in refreshDict.items():
        randMineID = refreshInfo["randMineID"]
        position = refreshInfo["position"]
        mineType = refreshInfo["mineType"]
        itemLV = refreshInfo["itemLV"]
        GameWorld.DebugAnswer(curPlayer, "位置索引=%s,坐标=%s,类型=%s,等级=%s,ID=%s" % (index, position, mineType, itemLV, randMineID))
    return
def __PrintMineItemLog(curPlayer, areaPlayerID, index):
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    mineItemData = mineItemMgr.GetMineItem(areaPlayerID, index)
    MineID = mineItemData.MineID
    MineType = mineItemData.MineType
    UpdTime = mineItemData.UpdTime
    Position = mineItemData.Position
    WorkerCount = mineItemData.WorkerCount
    WorkerState = mineItemData.WorkerState
    RobPlayerID = mineItemData.RobPlayerID
    RobWorkerCount = mineItemData.RobWorkerCount
    RobWorkerState = mineItemData.RobWorkerState
    MoveSpeed = getattr(mineItemData, GameWorldMineArea.MineItemAttr_MoveSpeed, 0)
    EndTime = getattr(mineItemData, GameWorldMineArea.MineItemAttr_EndTime, 0)
    GameWorld.DebugLog("i=%s,MineID=%s,Position=%s,WorkerCnt-State=(%s-%s),RobWorkerCnt-State=(%s-%s),RobPlayerID=%s,UpdTime=%s,MineType=%s"
                       % (index, MineID, Position, WorkerCount, WorkerState, RobWorkerCount, RobWorkerState,
                          RobPlayerID, GameWorld.ChangeTimeNumToStr(UpdTime), MineType), areaPlayerID)
    endTimeStr = ""
    remainHms = ""
    if MoveSpeed and EndTime:
        endTimeStr = GameWorld.ChangeTimeNumToStr(EndTime)
        remainSeconds = EndTime - int(time.time())
        remainH = remainSeconds / 3600
        remainM = remainSeconds % 3600 / 60
        remainS = remainSeconds % 60
        remainHms = "%02d:%02d:%02d" % (remainH, remainM, remainS)
        GameWorld.DebugLog("    MoveSpeed=%s,remainSeconds=%s(%s),EndTime=%s"
                           % (MoveSpeed, remainSeconds, remainHms, endTimeStr), areaPlayerID)
    GameWorld.DebugAnswer(curPlayer, "%s,ID(%s-%s),拉(%s-%s-%s),抢(%s-%s-%s),%s"
                          % (index, MineID, MineType, WorkerCount, WorkerState, areaPlayerID, RobWorkerCount, RobWorkerState, RobPlayerID, remainHms))
    return
def __ClearAreaData(curPlayer, areaPlayerID, isPop):
    mineIndexList = range(IpyGameDataPY.GetFuncCfg("MineAreaBase", 1))
    notifyPlayerIDListEx = []
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    for index in mineIndexList:
        mineItemData = mineItemMgr.GetMineItem(areaPlayerID, index)
        if mineItemData.RobPlayerID:
            notifyPlayerIDListEx.append(mineItemData.RobPlayerID)
        mineItemMgr.ClearMineItem(mineItemData)
    GameWorldMineArea.SyncMineAreaItemInfo(areaPlayerID, mineIndexList, notifyPlayerIDListEx=notifyPlayerIDListEx)
    if isPop:
        mineItemMgr.playerMineItemDict.pop(areaPlayerID, None)
        if areaPlayerID in mineItemMgr.realAreaPlayerIDList:
            mineItemMgr.realAreaPlayerIDList.remove(areaPlayerID)
        if areaPlayerID in mineItemMgr.fackAreaPlayerIDList:
            mineItemMgr.fackAreaPlayerIDList.remove(areaPlayerID)
    GameWorld.DebugAnswer(curPlayer, "清除福地数据! %s, isPop:%s" % (areaPlayerID, isPop))
    return
def __PrintAreaFuncInfo(curPlayer):
    ## 输出功能数据,开发测试用
    GameWorld.DebugAnswer(curPlayer, "----- 福地数据汇总 ----- %s" % GameWorld.GetGameWorld().GetTick(), False)
    GameWorld.DebugLog("---------------------")
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    GameWorld.DebugLog("假人数: %s %s" % (len(mineItemMgr.fackAreaPlayerIDList), mineItemMgr.fackAreaPlayerIDList))
    GameWorld.DebugLog("真人数: %s %s" % (len(mineItemMgr.realAreaPlayerIDList), mineItemMgr.realAreaPlayerIDList))
    GameWorld.DebugAnswer(curPlayer, "假人数: %s" % (len(mineItemMgr.fackAreaPlayerIDList)), False)
    GameWorld.DebugAnswer(curPlayer, "真人数: %s" % (len(mineItemMgr.realAreaPlayerIDList)), False)
    pullingTotal = 0
    for playerID, pullingItemList in mineItemMgr.pullingItemListDict.items():
        GameWorld.DebugLog("拉取中物品: playerID=%s,数量=%s" % (playerID, len(pullingItemList)))
        if pullingItemList:
            GameWorld.DebugAnswer(curPlayer, "拉取中物品:%s,数量=%s" % (playerID, len(pullingItemList)), False)
        pullingTotal += len(pullingItemList)
    GameWorld.DebugLog("等待结束总数: %s, 拉取中总数=%s" % (len(mineItemMgr.allMineItemByEndTimeList), pullingTotal))
    GameWorld.DebugAnswer(curPlayer, "等待结束总数:%s,拉取中总数:%s" % (len(mineItemMgr.allMineItemByEndTimeList), pullingTotal), False)
    for playerID, neighborIDList in mineItemMgr.neighborIDListDict.items():
        GameWorld.DebugLog("周围福地列表: playerID=%s,neighborIDList=%s" % (playerID, neighborIDList))
        GameWorld.DebugAnswer(curPlayer, "周围福地列表:%s,%s" % (playerID, neighborIDList), False)
    for playerID, socialIDList in mineItemMgr.socialIDListDict.items():
        GameWorld.DebugLog("道友福地列表: playerID=%s,socialIDList=%s" % (playerID, socialIDList))
        GameWorld.DebugAnswer(curPlayer, "道友福地列表:%s" % (playerID), False)
        GameWorld.DebugAnswer(curPlayer, " %s" % socialIDList[:len(socialIDList)/2], False)
        GameWorld.DebugAnswer(curPlayer, " %s" % socialIDList[len(socialIDList)/2:], False)
    for areaPlayerID, viewPlayerIDList in mineItemMgr.viewAreaPlayerIDDict.items():
        GameWorld.DebugLog("查看福地列表: areaPlayerID=%s,viewPlayerIDList=%s" % (areaPlayerID, viewPlayerIDList))
        GameWorld.DebugAnswer(curPlayer, "查看福地列表:%s,%s" % (areaPlayerID, viewPlayerIDList), False)
    awardMgr = PyDataManager.GetDBPyMineAreaAwardManager()
    awardPlayerIDList = awardMgr.playerAreaAwardDict.keys()
    GameWorld.DebugLog("未领取结算奖励玩家: %s" % awardPlayerIDList)
    GameWorld.DebugAnswer(curPlayer, "未领取结算奖励玩家: %s" % awardPlayerIDList, False)
    GameWorld.DebugLog("---------------------")
    GameWorld.DebugAnswer(curPlayer, "详见日志输出", False)
    return
ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
@@ -1122,13 +1122,14 @@
    
    return 0
def DebugAnswer(curPlayer, text):
def DebugAnswer(curPlayer, text, isLog=True):
    '''转码后再发DebugAnswer'''
    #===========================================================================
    # if not GetGameWorld().GetDebugLevel():
    #    return
    #===========================================================================
    DebugLog(text)
    if isLog:
        DebugLog(text)
    text = text.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())
    curPlayer.DebugAnswer(text)
    return
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldMineArea.py
New file
@@ -0,0 +1,1320 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GameWorldMineArea
#
# @todo:矿物福地
# @author hxp
# @date 2024-03-07
# @version 1.0
#
# 详细描述: 矿物福地
#
#-------------------------------------------------------------------------------
#"""Version = 2024-03-07 19:30"""
#-------------------------------------------------------------------------------
import GameWorld
import NetPackCommon
import PyDataManager
import ChPyNetSendPack
import PyGameDataStruct
import PlayerViewCache
import PlayerDBGSEvent
import PlayerControl
import IpyGameDataPY
import ShareDefine
import CommFunc
import operator
import random
import time
import uuid
Def_FakeAreaCount = 50 # 假人福地个数,一般就前期有用,上线后只能调大,不调小
Def_RecordMax = 50 # 每个玩家保留最近50条记录
Def_PositionMax = 100 # 最大距离,格
Def_PositionMid = Def_PositionMax / 2 # 中间距离
# 物品实例额外属性名
MineItemAttr_MoveSpeed = "MoveSpeed"
MineItemAttr_EndTime = "EndTime"
# 物品类型
MineType_Normal = 0 # 常规物品
MineType_Super = 1 # 超级物品
# 福地记录类型
MineAreaRecordType_Pull = 1 # 拉物品
MineAreaRecordType_BeRobbed = 2 # 被人抢
MineAreaAwardGetTick = "MineAreaAwardGetTick"
NeighborAreaRefreshTick = "NeighborAreaRefreshTick"
class DBPyMineAreaAwardManager(object):
    ## 福地奖励结算管理
    def __init__(self):
        self.playerAreaAwardDict = {} # {playerID:{GUID:tagDBPyMineAreaAward, ...}, ...}
        return
    def AddPlayerAreaAward(self, awardData):
        playerID = awardData.PlayerID
        if playerID not in self.playerAreaAwardDict:
            self.playerAreaAwardDict[playerID] = {}
        awardDict = self.playerAreaAwardDict[playerID]
        awardDict[awardData.GUID] = awardData
        return
    # 保存数据 存数据库和realtimebackup
    def GetSaveData(self):
        savaData = ""
        cntData = ""
        cnt = 0
        for awardDict in self.playerAreaAwardDict.values():
            for awardData in awardDict.values():
                cnt += 1
                savaData += awardData.getBuffer()
        GameWorld.Log("Save DBPyMineAreaAward count :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
    # 从数据库载入数据
    def LoadPyGameData(self, datas, pos, dataslen):
        cnt, pos = CommFunc.ReadDWORD(datas, pos)
        GameWorld.Log("Load DBPyMineAreaAward count :%s" % cnt)
        self.playerAreaAwardDict = {}
        for _ in xrange(cnt):
            awardData = PyGameDataStruct.tagDBPyMineAreaAward()
            awardData.clear()
            pos += awardData.readData(datas, pos, dataslen)
            self.AddPlayerAreaAward(awardData)
        return pos
class DBPyMineAreaRecordManager(object):
    ## 福地矿物记录管理
    def __init__(self):
        self.playerMineRecordListDict = {} # {playerID:[tagDBPyMineAreaRecord, ...], ...}
        return
    def AddPlayerRecord(self, recordData):
        playerID = recordData.PlayerID
        if playerID not in self.playerMineRecordListDict:
            self.playerMineRecordListDict[playerID] = []
        recordList = self.playerMineRecordListDict[playerID]
        recordList.append(recordData)
        return recordList
    # 保存数据 存数据库和realtimebackup
    def GetSaveData(self):
        savaData = ""
        cntData = ""
        cnt = 0
        for recordList in self.playerMineRecordListDict.values():
            for recordData in recordList:
                cnt += 1
                savaData += recordData.getBuffer()
        GameWorld.Log("Save DBPyMineAreaRecord count :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
    # 从数据库载入数据
    def LoadPyGameData(self, datas, pos, dataslen):
        cnt, pos = CommFunc.ReadDWORD(datas, pos)
        GameWorld.Log("Load DBPyMineAreaRecord count :%s" % cnt)
        self.playerMineRecordListDict = {}
        for _ in xrange(cnt):
            recordData = PyGameDataStruct.tagDBPyMineAreaRecord()
            recordData.clear()
            pos += recordData.readData(datas, pos, dataslen)
            self.AddPlayerRecord(recordData)
        return pos
class DBPyMineAreaItemManager(object):
    ## 福地矿物管理
    def __init__(self):
        self.Clear()
        return
    def Clear(self):
        self.playerMineItemDict = {} # 玩家福地物品信息 {playerID:{index:tagDBPyMineAreaItem, ...}, ...}
        self.allMineItemByEndTimeList = [] # 根据结束时间排序的所有矿物 [tagDBPyMineAreaItem, ...]
        self.pullingItemListDict = {} # 玩家拉取中的物品信息 {playerID:[tagDBPyMineAreaItem, ...], ...}
        self.freeSuperItemList = [] # 没人拉的超级物品实例列表 [tagDBPyMineAreaItem, ...]
        self.endSelfItemList = [] # 拉自己物品完结实例列表 [tagDBPyMineAreaItem, ...]
        self.endRobItemList = [] # 被抢劫物品完结实例列表 [tagDBPyMineAreaItem, ...]
        self.realAreaPlayerIDList = [] # 真实福地玩家ID列表
        self.fackAreaPlayerIDList = [] # 假人福地玩家ID列表
        self.viewAreaPlayerIDDict = {} # 正在查看某个福地中的玩家ID {areaPlayerID:[viewPlayerID, ...], ...}
        self.neighborIDListDict = {} # 玩家周围福地玩家ID列表 {playerID:[playerID, ...], ...}
        self.socialIDListDict = {} # 玩家有关系道友福地玩家ID列表 {playerID:[playerID, ...], ...} playerID列表倒序
        return
    def AddViewAreaPlayerID(self, viewPlayerID, areaPlayerID):
        if areaPlayerID not in self.viewAreaPlayerIDDict:
            self.viewAreaPlayerIDDict[areaPlayerID] = []
        viewPlayerIDList = self.viewAreaPlayerIDDict[areaPlayerID]
        if viewPlayerID not in viewPlayerIDList:
            viewPlayerIDList.append(viewPlayerID)
        return
    def DelViewAreaPlayerID(self, viewPlayerID):
        for viewPlayerIDList in self.viewAreaPlayerIDDict.values():
            if viewPlayerID in viewPlayerIDList:
                viewPlayerIDList.remove(viewPlayerID)
        return
    def AddPlayerPullingItem(self, playerID, mineItemData):
        if playerID not in self.pullingItemListDict:
            self.pullingItemListDict[playerID] = []
        pullingItemList = self.pullingItemListDict[playerID]
        if mineItemData not in pullingItemList:
            pullingItemList.append(mineItemData)
        if mineItemData in self.freeSuperItemList:
            self.freeSuperItemList.remove(mineItemData)
        return
    def RemovePlayerPullingItem(self, playerID, mineItemData):
        if playerID not in self.pullingItemListDict:
            self.pullingItemListDict[playerID] = []
        pullingItemList = self.pullingItemListDict[playerID]
        if mineItemData in pullingItemList:
            pullingItemList.remove(mineItemData)
        return
    def ClearMineItem(self, mineItemData):
        '''清除矿物,仅清除数据,对象保留,清除后 MineID 为0
        @param mineItemData: PyGameDataStruct.tagDBPyMineAreaItem()
        '''
        if mineItemData in self.allMineItemByEndTimeList:
            self.allMineItemByEndTimeList.remove(mineItemData)
        if mineItemData.PlayerID:
            self.RemovePlayerPullingItem(mineItemData.PlayerID, mineItemData)
        if mineItemData.RobPlayerID:
            self.RemovePlayerPullingItem(mineItemData.RobPlayerID, mineItemData)
        if mineItemData in self.freeSuperItemList:
            self.freeSuperItemList.remove(mineItemData)
        self.InitMineItem(mineItemData, mineItemData.PlayerID, mineItemData.Index)
        return
    def InitMineItem(self, mineItemData, playerID, index, mineID=0, mineType=0, position=""):
        ## 矿物初始化
        mineItemData.clear()
        mineItemData.PlayerID = playerID
        mineItemData.Index = index
        mineItemData.MineID = mineID
        mineItemData.MineType = mineType
        mineItemData.UpdTime = int(time.time())
        mineItemData.Position = "%s" % position
        mineItemData.PosLen = len(mineItemData.Position)
        # 不入库的属性
        setattr(mineItemData, MineItemAttr_EndTime, 0)
        setattr(mineItemData, MineItemAttr_MoveSpeed, 0)
        return
    def GetMineItem(self, playerID, index):
        '''获取玩家福地矿物
        @param playerID: 福地玩家ID
        @param index: 矿物所在福地索引
        @return: PyGameDataStruct.tagDBPyMineAreaItem()
        '''
        if playerID not in self.playerMineItemDict:
            self.playerMineItemDict[playerID] = {}
        itemDict = self.playerMineItemDict[playerID]
        if index in itemDict:
            mineItemData = itemDict[index]
        else:
            mineItemData = PyGameDataStruct.tagDBPyMineAreaItem()
            self.InitMineItem(mineItemData, playerID, index)
            itemDict[index] = mineItemData
            self.AddMineAreaPlayerID(playerID)
        return mineItemData
    def AddMineAreaPlayerID(self, playerID):
        if playerID > Def_FakeAreaCount:
            if playerID not in self.realAreaPlayerIDList:
                self.realAreaPlayerIDList.append(playerID)
        else:
            if playerID not in self.fackAreaPlayerIDList:
                self.fackAreaPlayerIDList.append(playerID)
        return
    # 保存数据 存数据库和realtimebackup
    def GetSaveData(self):
        savaData = ""
        cntData = ""
        cnt = 0
        for itemDict in self.playerMineItemDict.values():
            for mineItemData in itemDict.values():
                cnt += 1
                savaData += mineItemData.getBuffer()
        GameWorld.Log("Save DBPyMineAreaItem count :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
    # 从数据库载入数据
    def LoadPyGameData(self, datas, pos, dataslen):
        cnt, pos = CommFunc.ReadDWORD(datas, pos)
        GameWorld.Log("Load DBPyMineAreaItem count :%s" % cnt)
        self.Clear()
        for _ in xrange(cnt):
            mineItemData = PyGameDataStruct.tagDBPyMineAreaItem()
            mineItemData.clear()
            pos += mineItemData.readData(datas, pos, dataslen)
            OnLoadMineItemData(mineItemData)
        OnLoadMineItemOK()
        return pos
def DoMineAreaFuncOpen(curPlayer):
    ## 福地功能开启
    playerID = curPlayer.GetPlayerID()
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    # 还没有福地物品数据,则刷新初始化
    if playerID not in mineItemMgr.playerMineItemDict:
        __DoMineItemRefresh(playerID, curPlayer)
    return
def OnPlayerLogin(curPlayer):
    playerID = curPlayer.GetPlayerID()
    # 自己福地数据
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    if playerID in mineItemMgr.playerMineItemDict:
        NetPackCommon.SendFakePack(curPlayer, __GetMineAreaInfoPack([[playerID, []]]))
    # 拉取中的物品数据
    SyncPullingAreaMineInfo(curPlayer)
    # 有未领取的结算奖励
    awardMgr = PyDataManager.GetDBPyMineAreaAwardManager()
    awardDict = awardMgr.playerAreaAwardDict.get(playerID, {})
    if awardDict:
        SyncMineAwardAward(curPlayer)
    return
def OnLoadMineItemData(mineItemData):
    ## 加载矿物
    playerID = mineItemData.PlayerID
    index = mineItemData.Index
    mineID = mineItemData.MineID
    if not mineID:
        return
    mineType = mineItemData.MineType
    workerCount = mineItemData.WorkerCount
    robPlayerID = mineItemData.RobPlayerID
    robWorkerCount = mineItemData.RobWorkerCount
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    if playerID not in mineItemMgr.playerMineItemDict:
        mineItemMgr.playerMineItemDict[playerID] = {}
    itemDict = mineItemMgr.playerMineItemDict[playerID]
    itemDict[index] = mineItemData
    mineItemMgr.AddMineAreaPlayerID(playerID)
    if mineType == MineType_Super and not workerCount and not robWorkerCount and mineItemData not in mineItemMgr.freeSuperItemList:
        mineItemMgr.freeSuperItemList.append(mineItemData)
    if workerCount:
        mineItemMgr.AddPlayerPullingItem(playerID, mineItemData)
    if robPlayerID and robWorkerCount:
        mineItemMgr.AddPlayerPullingItem(robPlayerID, mineItemData)
    __RefreshMineItemSpeed(mineItemData)
    return
def OnLoadMineItemOK():
    __SortMineItem()
    __MakeFackArea()
    # 启动默认补充空位置物品...
    refreshIndexList = range(IpyGameDataPY.GetFuncCfg("MineAreaBase", 1))
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    for areaPlayerID, itemDict in mineItemMgr.playerMineItemDict.items():
        emptyIndexList = []
        for index in refreshIndexList:
            if index not in itemDict:
                emptyIndexList.append(index)
                continue
            mineItemData = itemDict[index]
            if not mineItemData or not mineItemData.MineID:
                emptyIndexList.append(index)
                continue
        if not emptyIndexList:
            continue
        GameWorld.DebugLog("启动默认补充空位置物品: areaPlayerID=%s,emptyIndexList=%s" % (areaPlayerID, emptyIndexList))
        __DoMineItemRefresh(areaPlayerID, refreshIndexList=emptyIndexList)
    return
def __MakeFackArea():
    # 生成假人福地数据
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    if len(mineItemMgr.playerMineItemDict) >= Def_FakeAreaCount:
        return
    needFackCount = Def_FakeAreaCount - len(mineItemMgr.playerMineItemDict)
    fackPlayerID = 0
    while needFackCount > 0 and fackPlayerID < Def_FakeAreaCount:
        fackPlayerID += 1
        if fackPlayerID in mineItemMgr.playerMineItemDict:
            continue
        if __DoMineItemRefresh(fackPlayerID, isNotify=False):
            GameWorld.DebugLog("新增福地假人: %s" % fackPlayerID)
            needFackCount -= 1
    return
def __SortMineItem():
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    mineItemMgr.allMineItemByEndTimeList.sort(key=operator.attrgetter(MineItemAttr_EndTime))
    return
def __RefreshMineItemPosition(mineItemData, curTime):
    ## 刷新矿物坐标
    playerID = mineItemData.PlayerID
    index = mineItemData.Index
    mineID = mineItemData.MineID
    curPos = GameWorld.ToIntDef(mineItemData.Position, Def_PositionMid)
    if not playerID or not mineID:
        return curPos
    curWorkerCount = mineItemData.WorkerCount
    robWorkerCount = mineItemData.RobWorkerCount
    if not curWorkerCount and not robWorkerCount:
        return curPos
    moveSpeed = getattr(mineItemData, MineItemAttr_MoveSpeed)
    if not moveSpeed:
        return curPos
    passSeconds = curTime - mineItemData.UpdTime
    if passSeconds <= 0 or not moveSpeed:
        return curPos
    moveDir = -1 if curWorkerCount >= robWorkerCount else 1 # 移动方向,-1-下; 1-上
    moveDist = moveSpeed * passSeconds * moveDir
    updPos = min(max(0, curPos + moveDist), Def_PositionMax)
    mineItemData.Position = "%s" % updPos
    mineItemData.PosLen = len(mineItemData.Position)
    mineItemData.UpdTime = curTime
    GameWorld.DebugLog("更新矿物坐标: playerID=%s,index=%s,mineID=%s,curWorkerCount=%s,robWorkerCount=%s,curPos=%s,moveSpeed=%s,passSeconds=%s,moveDist=%s,updPos=%s"
                       % (playerID, index, mineID, curWorkerCount, robWorkerCount, curPos, moveSpeed, passSeconds, moveDist, updPos))
    return updPos
def __RefreshMineItemSpeed(mineItemData, isSort=False):
    ## 刷新矿物速度、完成时间
    playerID = mineItemData.PlayerID
    index = mineItemData.Index
    mineID = mineItemData.MineID
    if not playerID or not mineID:
        return
    curPos = GameWorld.ToIntDef(mineItemData.Position, Def_PositionMid)
    allMineItemByEndTimeList = PyDataManager.GetDBPyMineAreaItemManager().allMineItemByEndTimeList
    curWorkerCount = mineItemData.WorkerCount
    robWorkerCount = mineItemData.RobWorkerCount
    if not curWorkerCount and not robWorkerCount:
        setattr(mineItemData, MineItemAttr_EndTime, 0)
        setattr(mineItemData, MineItemAttr_MoveSpeed, 0)
        if mineItemData in allMineItemByEndTimeList:
            allMineItemByEndTimeList.remove(mineItemData)
        return
    GameWorld.DebugLog("更新矿物时间速度: playerID=%s,index=%s,mineID=%s,curWorkerCount=%s,robWorkerCount=%s,curPos=%s"
                       % (playerID, index, mineID, curWorkerCount, robWorkerCount, curPos))
    curWorkerState = mineItemData.WorkerState
    robWorkerState = mineItemData.RobWorkerState
    ret = __calcMineItemSpeed(mineID, curPos, curWorkerCount, curWorkerState, robWorkerCount, robWorkerState)
    if not ret:
        return
    moveSpeed, needSeconds = ret
    updTime = mineItemData.UpdTime
    endTime = updTime + needSeconds
    GameWorld.DebugLog("    updTime=%s,needSeconds=%s,endTime=%s"
                       % (GameWorld.ChangeTimeNumToStr(updTime), needSeconds, GameWorld.ChangeTimeNumToStr(endTime)))
    setattr(mineItemData, MineItemAttr_EndTime, endTime)
    setattr(mineItemData, MineItemAttr_MoveSpeed, moveSpeed)
    if mineItemData not in allMineItemByEndTimeList:
        allMineItemByEndTimeList.append(mineItemData)
    if isSort:
        __SortMineItem()
    return True
def __calcMineItemSpeed(mineID, curPos, curWorkerCount, curWorkerState, robWorkerCount, robWorkerState):
    ## 计算拉物品速度,这里只处理计算逻辑,实际应用由调用者决定
    # @param return: moveSpeed, needSeconds 或  异常返回None
    if not curWorkerCount and not robWorkerCount:
        return 0, 0
    ipyData = IpyGameDataPY.GetIpyGameData("MineAreaItem", mineID)
    if not ipyData:
        return
    itemWeight = ipyData.GetItemWeight()
    moveDir = -1 if curWorkerCount >= robWorkerCount else 1 # 移动方向,-1-下; 1-上
    # 下 - 拉回
    if moveDir == -1:
        dist = curPos # 还需移动距离
        workerState = curWorkerState
        workerCount, batWorkerCount = curWorkerCount, robWorkerCount
    # 上 - 抢劫
    else:
        dist = Def_PositionMax - curPos
        workerState = robWorkerState
        workerCount, batWorkerCount = robWorkerCount, curWorkerCount
    workerStateTimeList = IpyGameDataPY.GetFuncEvalCfg("MineAreaWorkCalc", 1) # 疲劳状态单位耗时列表
    workerCountRatioList = IpyGameDataPY.GetFuncEvalCfg("MineAreaWorkCalc", 2) # 人数耗时比率列表
    workerBattleRatioList = IpyGameDataPY.GetFuncEvalCfg("MineAreaWorkCalc", 3) # 对抗人数耗时比率列表
    baseTime = workerStateTimeList[len(workerStateTimeList) - 1] if workerState >= len(workerStateTimeList) else workerStateTimeList[workerState]
    workRatio = workerCountRatioList[len(workerCountRatioList) - 1] if workerCount > len(workerCountRatioList) else workerCountRatioList[workerCount - 1]
    battleRatio = 1 # 没人对抗时,默认1
    if batWorkerCount > 0:
        battleRatio = workerBattleRatioList[len(workerBattleRatioList) - 1] if batWorkerCount > len(workerBattleRatioList) else workerBattleRatioList[batWorkerCount - 1]
    needSeconds = int(dist * itemWeight * baseTime * workRatio * battleRatio) # 还需工作时长,秒
    moveSpeed = dist / float(needSeconds) # 移动速度  x格/秒
    needHms = "%02d:%02d:%02d" % (needSeconds / 3600, needSeconds % 3600 / 60, needSeconds % 60)
    GameWorld.DebugLog("    mineID=%s,curPos=%s,curWorkerCount=%s,curWorkerState=%s,robWorkerCount=%s,robWorkerState=%s"
                       % (mineID, curPos, curWorkerCount, curWorkerState, robWorkerCount, robWorkerState))
    GameWorld.DebugLog("    moveDir=%s,dist=%s,itemWeight=%s,baseTime=%s,workRatio=%s,battleRatio=%s,needSeconds=%s(%s),moveSpeed=%s"
                       % (moveDir, dist, itemWeight, baseTime, workRatio, battleRatio, needSeconds, needHms, moveSpeed))
    return moveSpeed, needSeconds
def OnProcessOnMinute():
    ## 定时处理,每分钟一次
    __Process_SysRefresh()
    return
def __Process_SysRefresh():
    ## 系统定时刷新
    sysRefreshHMList = IpyGameDataPY.GetFuncEvalCfg("MineAreaSysRefresh", 1)
    if not sysRefreshHMList:
        return
    dayTime = GameWorld.GetServerTime()
    curHourMinute = [dayTime.hour, dayTime.minute]
    if curHourMinute not in sysRefreshHMList:
        return
    GameWorld.Log("福地系统定时刷新! %s" % str(curHourMinute))
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    for playerID in mineItemMgr.playerMineItemDict.keys():
        __DoMineItemRefresh(playerID, isSuper=True)
    return
def OnMineItemTimeProcess(curTime, tick):
    ## 定时处理,每秒触发一次
    # 待优化处理...
    # 定时删除多余数据,如过天处理,多余记录
    # 合服多余数据清理,合服假人ID重复问题
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    __Process_EndItemRefresh(mineItemMgr.endSelfItemList, IpyGameDataPY.GetFuncCfg("MineAreaSysRefresh", 2), curTime)
    __Process_EndItemRefresh(mineItemMgr.endRobItemList, IpyGameDataPY.GetFuncCfg("MineAreaSysRefresh", 3), curTime)
    __Process_SuperItem(curTime)
    __Process_MineItemByEndTimeList(curTime)
    return
def __Process_EndItemRefresh(endItemList, refreshCD, curTime):
    ## 定时处理空位置物品刷新
    if not endItemList:
        return
    doCount = len(endItemList)
    index = 0
    while doCount > 0 and index < len(endItemList):
        doCount -= 1
        mineItemData = endItemList[index]
        if not mineItemData or mineItemData.MineID:
            # None 或 已经有物品了,不再处理,直接移除
            endItemList.pop(index)
            continue
        UpdTime = mineItemData.UpdTime
        if curTime - UpdTime < refreshCD:
            # 因为是按结束先后顺序添加的,所以只要还在CD,则后面的一定也是CD中
            break
        areaPlayerID = mineItemData.PlayerID
        itemIndex = mineItemData.Index
        if __DoMineItemRefresh(areaPlayerID, refreshIndexList=[itemIndex]):
            endItemList.pop(index) # 成功刷新后直接移除
            continue
        index += 1
    return
def __Process_SuperItem(curTime):
    ## 定时处理超级物品
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    freeSuperItemList = mineItemMgr.freeSuperItemList
    if not freeSuperItemList:
        return
    superItemExistSeconds = IpyGameDataPY.GetFuncCfg("MineAreaSuperItem", 1)
    doCount = len(freeSuperItemList)
    index = 0
    while doCount > 0 and freeSuperItemList:
        doCount -= 1
        mineItemData = freeSuperItemList[index]
        if not mineItemData or mineItemData.WorkerCount or mineItemData.RobWorkerCount:
            # None 或 已经有人再拉了,不再处理,直接移除
            freeSuperItemList.pop(index)
            continue
        UpdTime = mineItemData.UpdTime
        if curTime - UpdTime < superItemExistSeconds:
            break
        areaPlayerID = mineItemData.PlayerID
        itemIndex = mineItemData.Index
        GameWorld.DebugLog("超级物品过期! areaPlayerID=%s,itemIndex=%s" % (areaPlayerID, itemIndex))
        mineItemMgr.ClearMineItem(mineItemData)
        __OnEndSelfItem(mineItemMgr, mineItemData, areaPlayerID, itemIndex)
        SyncMineAreaItemInfo(areaPlayerID, [itemIndex])
    return
def __Process_MineItemByEndTimeList(curTime):
    ## 定时处理拉时间到物品
    allMineItemByEndTimeList = PyDataManager.GetDBPyMineAreaItemManager().allMineItemByEndTimeList
    if not allMineItemByEndTimeList:
        return
    index = 0
    doCount = len(allMineItemByEndTimeList)
    while doCount > 0 and allMineItemByEndTimeList:
        doCount -= 1
        mineItemData = allMineItemByEndTimeList[index]
        endTime = getattr(mineItemData, MineItemAttr_EndTime)
        if curTime < endTime:
            break
        ret = __EndMineItemByTime(mineItemData.PlayerID, mineItemData.Index, curTime)
        if ret == None:
            if index < len(allMineItemByEndTimeList):
                allMineItemByEndTimeList.pop(index)
        elif ret == False:
            index += 1
    return
def __EndMineItemByTime(areaPlayerID, itemIndex, curTime):
    ## 根据时间结束矿物
    ## @return: 是否结束,None-异常情况
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    mineItemData = mineItemMgr.GetMineItem(areaPlayerID, itemIndex)
    mineID = mineItemData.MineID
    if not mineID:
        return
    useWorkerCount = 1
    notifyPlayerIDListEx = []
    curPos = __RefreshMineItemPosition(mineItemData, curTime)
    # 兼容1格
    # 自己拉回
    if curPos <= 1:
        awardPlayerID = areaPlayerID
        useWorkerCount = mineItemData.WorkerCount
    # 抢劫拉走
    elif curPos >= Def_PositionMax - 1:
        awardPlayerID = mineItemData.RobPlayerID
        useWorkerCount = mineItemData.RobWorkerCount
        notifyPlayerIDListEx = [awardPlayerID]
    else:
        return False
    ipyData = IpyGameDataPY.GetIpyGameData("MineAreaItem", mineID)
    if not ipyData:
        return
    # 奖励玩家并不一定在线,统一添加进奖励,由玩家请求结算
    awardData = PyGameDataStruct.tagDBPyMineAreaAward()
    awardData.GUID = str(uuid.uuid1())
    awardData.GUIDLen = len(awardData.GUID)
    awardData.PlayerID = awardPlayerID
    awardData.AwardTime = int(time.time())
    awardData.MineID = mineID
    awardData.WorkerCount = useWorkerCount
    awardData.AreaPlayerID = areaPlayerID
    PyDataManager.GetDBPyMineAreaAwardManager().AddPlayerAreaAward(awardData)
    # 通知有奖励
    awardPlayer = GameWorld.GetPlayerManager().FindPlayerByID(awardPlayerID)
    if awardPlayer:
        SyncMineAwardAward(awardPlayer)
    GameWorld.DebugLog("根据时间结束物品: areaPlayerID=%s,itemIndex=%s,mineID=%s,awardPlayerID=%s"
                       % (areaPlayerID, itemIndex, mineID, awardPlayerID))
    mineItemMgr.ClearMineItem(mineItemData)
    #增加记录
    AddMineItemRecord(awardPlayerID, MineAreaRecordType_Pull, areaPlayerID, mineID, curTime)
    if areaPlayerID != awardPlayerID:
        AddMineItemRecord(areaPlayerID, MineAreaRecordType_BeRobbed, awardPlayerID, mineID, curTime)
        # 被抢的
        if IpyGameDataPY.GetFuncCfg("MineAreaSysRefresh", 3) > 0:
            mineItemMgr.endRobItemList.append(mineItemData)
        else:
            __DoMineItemRefresh(areaPlayerID, isNotify=False, refreshIndexList=[itemIndex])
    else:
        # 拉自己的
        __OnEndSelfItem(mineItemMgr, mineItemData, areaPlayerID, itemIndex)
    SyncMineAreaItemInfo(areaPlayerID, [itemIndex], notifyPlayerIDListEx)
    return True
def __OnEndSelfItem(mineItemMgr, mineItemData, areaPlayerID, itemIndex):
    # 自己的物品结束,包含自己拉的,自己消失的(如超级物品),不含被抢的
    if IpyGameDataPY.GetFuncCfg("MineAreaSysRefresh", 2) > 0:
        mineItemMgr.endSelfItemList.append(mineItemData)
    else:
        __DoMineItemRefresh(areaPlayerID, isNotify=False, refreshIndexList=[itemIndex])
    return
def AddMineItemRecord(playerID, recordType, tagPlayerID, mineID, curTime):
    recordData = PyGameDataStruct.tagDBPyMineAreaRecord()
    recordData.PlayerID = playerID
    recordData.RecordType = recordType
    recordData.TagPlayerID = tagPlayerID
    recordData.MineID = mineID
    recordData.RecordTime = curTime
    recordMgr = PyDataManager.GetDBPyMineAreaRecordManager()
    recordList = recordMgr.AddPlayerRecord(recordData)
    # 被人抢,更新关系福地ID记录
    if recordData.RecordType == MineAreaRecordType_BeRobbed and playerID > Def_FakeAreaCount:
        __DoUpdSocialPlayerIDList(playerID)
    if len(recordList) > Def_RecordMax:
        recordList.pop(0) # 删除最早一条
    return
def __DoUpdSocialPlayerIDList(playerID):
    ## 更新有关系的道友ID列表
    recordMgr = PyDataManager.GetDBPyMineAreaRecordManager()
    recordList = recordMgr.playerMineRecordListDict.get(playerID, [])
    socialAreaMax = IpyGameDataPY.GetFuncCfg("MineAreaRob", 1) # 道友福地个数
    socialIDList = [] # 反序
    for recData in recordList[::-1]:
        if recData.RecordType != MineAreaRecordType_BeRobbed:
            ## 优先保留被抢记录关系玩家
            continue
        if recData.TagPlayerID not in socialIDList:
            socialIDList.append(recData.TagPlayerID)
            if len(socialIDList) >= socialAreaMax:
                break
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    socialIDListBef = mineItemMgr.socialIDListDict.get(playerID, [])
    # 优先使用历史记录
    if len(socialIDList) < socialAreaMax:
        for socialIDBef in socialIDListBef:
            if socialIDBef not in socialIDList:
                socialIDList.append(socialIDBef)
                if len(socialIDList) >= socialAreaMax:
                    break
    # 优先随机真人
    if len(socialIDList) < socialAreaMax and mineItemMgr.realAreaPlayerIDList:
        random.shuffle(mineItemMgr.realAreaPlayerIDList)
        for areaPlayerID in mineItemMgr.realAreaPlayerIDList:
            if areaPlayerID not in socialIDList and areaPlayerID != playerID:
                socialIDList.append(areaPlayerID)
                if len(socialIDList) >= socialAreaMax:
                    break
    # 不够补充假人
    if len(socialIDList) < socialAreaMax and mineItemMgr.fackAreaPlayerIDList:
        random.shuffle(mineItemMgr.fackAreaPlayerIDList)
        for areaPlayerID in mineItemMgr.fackAreaPlayerIDList:
            if areaPlayerID not in socialIDList:
                socialIDList.append(areaPlayerID)
                if len(socialIDList) >= socialAreaMax:
                    break
    mineItemMgr.socialIDListDict[playerID] = socialIDList
    return socialIDList
def MapServer_MineArea(curPlayer, msgList):
    mapID = curPlayer.GetRealMapID()
    playerID = curPlayer.GetPlayerID()
    GameWorld.DebugLog("MapServer_MineArea mapID=%s,msgList=%s" % (mapID, msgList), playerID)
    if not msgList:
        return
    msgType, dataMsg = msgList
    ret = None
    # 拉物品
    if msgType == "Pull":
        __DoPullItem(playerID, curPlayer, dataMsg)
    # 刷新福地物品
    elif msgType == "MineItemRefresh":
        playerID, isSuper = dataMsg
        __DoMineItemRefresh(playerID, curPlayer, isSuper=isSuper)
    # 地图结算奖励OK
    elif msgType == "MineAreaAwardGetOK":
        __DoMineAreaAwardGetOK(curPlayer, dataMsg)
    if ret == None:
        return
    return msgList + [ret]
def __DoPullItem(playerID, curPlayer, dataMsg):
    areaPlayerID, itemIndex, workerCount, workerState, workerTotal, isPreview = dataMsg
    if itemIndex < 0 or itemIndex >= IpyGameDataPY.GetFuncCfg("MineAreaBase", 1):
        GameWorld.ErrLog("不存在该福地物品位置索引! itemIndex=%s" % itemIndex)
        return
    if workerCount <= 0:
        if not isPreview:
            __DoCancelPull(playerID, areaPlayerID, itemIndex)
        return
    GameWorld.DebugLog("请求福地拉物品! areaPlayerID=%s,itemIndex=%s,workerCount=%s,workerState=%s,workerTotal=%s,isPreview=%s"
                       % (areaPlayerID, itemIndex, workerCount, workerState, workerTotal, isPreview), playerID)
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    mineItemData = mineItemMgr.GetMineItem(areaPlayerID, itemIndex)
    mineID = mineItemData.MineID
    if not mineID:
        GameWorld.ErrLog("该福地位置没有矿物,无法拉取! areaPlayerID=%s,itemIndex=%s" % (areaPlayerID, itemIndex), playerID)
        return
    if mineItemData.MineType == MineType_Super:
        if playerID != areaPlayerID:
            GameWorld.DebugLog("福地超级物品,仅自己可拉! areaPlayerID=%s,itemIndex=%s" % (areaPlayerID, itemIndex), playerID)
            return
    ipyData = IpyGameDataPY.GetIpyGameData("MineAreaItem", mineID)
    if not ipyData:
        return
    itemLV = ipyData.GetItemLV()
    itemLVWorkerMaxList = IpyGameDataPY.GetFuncEvalCfg("MineAreaBase", 3)
    assignMax = itemLVWorkerMaxList[itemLV - 1] if itemLV <= len(itemLVWorkerMaxList) else itemLVWorkerMaxList[-1] # 最大可上工人数
    atWorkCount = 0 # 已经在其他物品工作的工人数
    pullingItemList = mineItemMgr.pullingItemListDict.get(playerID, [])
    for pullItemData in pullingItemList:
        if pullItemData.PlayerID == areaPlayerID and pullItemData.Index == itemIndex:
            # 对同一物品操作,不算工作人数,可能是修改人数
            continue
        if pullItemData.PlayerID == playerID:
            atWorkCount += pullItemData.WorkerCount
        elif pullItemData.RobPlayerID == playerID:
            atWorkCount += pullItemData.RobWorkerCount
            if pullItemData.PlayerID == areaPlayerID:
                GameWorld.DebugLog("不能同时抢劫同个人多个物品! 已经在抢福地位置: areaPlayerID=%s,index=%s" % (areaPlayerID, pullItemData.Index), playerID)
                return
    freeWorkerCount = workerTotal - atWorkCount # 空闲工人数
    assignWorkerCount = min(freeWorkerCount, assignMax, workerCount) # 实际可派遣的工人数
    if assignWorkerCount <= 0:
        GameWorld.DebugLog("没有工人可派遣! atWorkCount=%s,workerTotal=%s,assignWorkerCount=%s" % (atWorkCount, workerTotal, assignWorkerCount), playerID)
        return
    curTime = int(time.time())
    # 先刷新下物品最新位置
    __RefreshMineItemPosition(mineItemData, curTime)
    if isPreview:
        ## 预览速度时间
        curPos = GameWorld.ToIntDef(mineItemData.Position, Def_PositionMid)
        if playerID == areaPlayerID:
            curWorkerCount = assignWorkerCount
            curWorkerState = workerState
            robWorkerCount = mineItemData.RobWorkerCount
            robWorkerState = mineItemData.RobWorkerState
        else:
            curWorkerCount = mineItemData.WorkerCount
            curWorkerState = mineItemData.WorkerState
            robWorkerCount = assignWorkerCount
            robWorkerState = workerState
        ret = __calcMineItemSpeed(mineID, curPos, curWorkerCount, curWorkerState, robWorkerCount, robWorkerState)
        if not ret:
            return
        _, needSeconds = ret
        if curPlayer:
            clientPack = ChPyNetSendPack.tagGCMineItemPullPreviewRet()
            clientPack.PlayerID = areaPlayerID
            clientPack.ItemIndex = itemIndex
            clientPack.WorkerCount = assignWorkerCount
            clientPack.NeedSeconds = needSeconds
            NetPackCommon.SendFakePack(curPlayer, clientPack)
        return
    notifyPlayerIDListEx = []
    # 替换新数据
    if playerID == areaPlayerID:
        mineItemData.WorkerCount = assignWorkerCount
        mineItemData.WorkerState = workerState
    else:
        mineItemData.RobPlayerID = playerID
        mineItemData.RobWorkerCount = assignWorkerCount
        mineItemData.RobWorkerState = workerState
        notifyPlayerIDListEx = [playerID]
    mineItemData.UpdTime = curTime
    mineItemMgr.AddPlayerPullingItem(playerID, mineItemData)
    # 重新刷新下速度时间
    __RefreshMineItemSpeed(mineItemData, True)
    SyncMineAreaItemInfo(areaPlayerID, [itemIndex], notifyPlayerIDListEx)
    return
def __DoCancelPull(playerID, areaPlayerID, itemIndex):
    ## 取消拉取
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    mineItemData = mineItemMgr.GetMineItem(areaPlayerID, itemIndex)
    mineID = mineItemData.MineID
    if not mineID:
        return
    notifyPlayerIDListEx = []
    if mineItemData.MineType == MineType_Super:
        mineItemMgr.ClearMineItem(mineItemData)
        __OnEndSelfItem(mineItemMgr, mineItemData, areaPlayerID, itemIndex)
    else:
        curTime = int(time.time())
        # 先刷新下物品最新位置
        __RefreshMineItemPosition(mineItemData, curTime)
        # 替换新数据
        if playerID == areaPlayerID:
            mineItemData.WorkerCount = 0
            mineItemData.WorkerState = 0
        else:
            mineItemData.RobPlayerID = 0
            mineItemData.RobWorkerCount = 0
            mineItemData.RobWorkerState = 0
            notifyPlayerIDListEx = [playerID]
        mineItemData.UpdTime = curTime
        mineItemMgr.RemovePlayerPullingItem(playerID, mineItemData)
        # 重新刷新下速度时间
        __RefreshMineItemSpeed(mineItemData, True)
    SyncMineAreaItemInfo(areaPlayerID, [itemIndex], notifyPlayerIDListEx)
    return
def __DoMineItemRefresh(areaPlayerID, areaPlayer=None, isSys=False, isSuper=False, isNotify=True, refreshIndexList=None, setPosition=None, setItemLV=None, setMineID=None):
    '''刷新福地物品
    @param areaPlayerID: 福地玩家ID,可能是假人
    @param areaPlayer: 福地玩家实例
    @param isSuper: 是否超级刷新,默认刷1个时效满级物品,默认自己可采,取消后消失,时间到没采也消失
    @param refreshIndexList: 指定只刷位置索引列表,没有指定则只刷新可刷新的
    @param setPosition: 指定坐标位置,没有指定则随机
    @param setItemLV: 指定只刷某个等级物品,没有指定则随机
    @param setMineID: 指定只刷某个ID,没有指定则随机
    '''
    GameWorld.DebugLog("刷新福地物品: refreshIndexList=%s,isSys=%s,isSuper=%s" % (refreshIndexList, isSys, isSuper), areaPlayerID)
    if setPosition or setItemLV or setMineID:
        GameWorld.DebugLog("    setPosition=%s,setItemLV=%s,setMineID=%s" % (setPosition, setItemLV, setMineID), areaPlayerID)
    playerLV = 0
    if areaPlayerID > Def_FakeAreaCount:
        if areaPlayer and areaPlayer.GetPlayerID() == areaPlayerID:
            playerLV = areaPlayer.GetLV()
        else:
            tagCacheDict = PlayerViewCache.GetCachePropDataDict(PlayerViewCache.FindViewCache(areaPlayerID))
            playerLV = tagCacheDict.get("LV", 0)
        GameWorld.DebugLog("    取玩家等级 playerLV=%s" % (playerLV), areaPlayerID)
    if not playerLV:
        # 取世界等级
        playerLV = max(1, PlayerDBGSEvent.GetDBGSTrig_ByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv))
        GameWorld.DebugLog("    取世界等级 playerLV=%s" % (playerLV), areaPlayerID)
    randWeightList = []
    randWeightListSuper = []
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in range(ipyDataMgr.GetMineAreaItemCount()):
        ipyData = ipyDataMgr.GetMineAreaItemByIndex(index)
        mineID = ipyData.GetMineID()
        limitLV = ipyData.GetLimitLV()
        if limitLV and playerLV < limitLV:
            continue
        if setItemLV and setItemLV != ipyData.GetItemLV():
            continue
        if setMineID and setMineID != mineID:
            continue
        weight = ipyData.GetRefreshWeightSuper()
        if weight:
            randWeightListSuper.append([weight, ipyData])
        weight = ipyData.GetRefreshWeightSys() if isSys else ipyData.GetRefreshWeight()
        if weight:
            randWeightList.append([weight, ipyData])
    #GameWorld.DebugLog("    randWeightList=%s" % randWeightList, areaPlayerID)
    #GameWorld.DebugLog("    randWeightListSuper=%s" % randWeightListSuper, areaPlayerID)
    if not randWeightList and not randWeightListSuper:
        return
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    randDist = IpyGameDataPY.GetFuncCfg("MineAreaBase", 2)
    superCount = 0
    superCountMax = 1 # 每次刷新最大刷出超级物品数量,已经刷新出的不计算在内
    refreshDict = {}
    if not refreshIndexList:
        refreshIndexList = range(IpyGameDataPY.GetFuncCfg("MineAreaBase", 1))
    for index in refreshIndexList:
        mineItemData = mineItemMgr.GetMineItem(areaPlayerID, index)
        if mineItemData.MineID and (mineItemData.WorkerCount or mineItemData.RobWorkerCount):
            # 有人了,不刷新
            continue
        randIpyData = None
        mineType = MineType_Normal
        if isSuper and superCount < superCountMax:
            randIpyData = GameWorld.GetResultByWeightList(randWeightListSuper)
            if randIpyData:
                superCount += 1
                mineType = MineType_Super
        else:
            randIpyData = GameWorld.GetResultByWeightList(randWeightList)
        if not randIpyData:
            continue
        randMineID = randIpyData.GetMineID()
        itemLV = randIpyData.GetItemLV()
        if setPosition:
            position = min(Def_PositionMax - 1, max(1, setPosition))
        else:
            position = random.randint(Def_PositionMid - randDist, Def_PositionMid + randDist) # 随机位置
        mineItemMgr.InitMineItem(mineItemData, areaPlayerID, index, randMineID, mineType, position)
        if mineType == MineType_Super and mineItemData not in mineItemMgr.freeSuperItemList:
            mineItemMgr.freeSuperItemList.append(mineItemData)
        refreshDict[index] = {"randMineID":randMineID, "position":position, "mineType":mineType, "itemLV":itemLV}
        GameWorld.DebugLog("    index=%s,randMineID=%s,position=%s,mineType=%s,itemLV=%s" % (index, randMineID, position, mineType, itemLV), areaPlayerID)
    if isNotify and refreshDict:
        SyncMineAreaItemInfo(areaPlayerID, refreshDict.keys())
    return refreshDict
#// B0 33 福地查看 #tagCGMineAreaView
#
#struct    tagCGMineAreaView
#{
#    tagHead        Head;
#    BYTE        QueryType;    // 查询同步类型:0-后端主动同步;1-查看指定福地;2-查看道友福地列表;3-查看周围随机福地列表;4-退出他人福地
#    DWORD        QueryValue;    // 查询值,类型1时-发送目标玩家ID;3时-发送是否重新随机
#};
def OnMineAreaView(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    queryType = clientData.QueryType
    queryValue = clientData.QueryValue
    # 查看指定福地
    if queryType == 1:
        areaPlayerID = queryValue if queryValue > 0 else  playerID
        mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
        if areaPlayerID not in mineItemMgr.playerMineItemDict:
            GameWorld.DebugLog("不存在该福地! areaPlayerID=%s" % areaPlayerID)
            return
        if playerID != areaPlayerID:
            mineItemMgr.AddViewAreaPlayerID(playerID, areaPlayerID)
        clientPack = __GetMineAreaInfoPack([[areaPlayerID, []]], queryType, queryValue)
        NetPackCommon.SendFakePack(curPlayer, clientPack)
    # 查看道友福地列表
    elif queryType == 2:
        SyncSocialAreaInfo(curPlayer, queryType, queryValue)
    # 查看周围随机福地列表
    elif queryType == 3:
        SyncNeighborAreaInfo(curPlayer, tick, queryType, queryValue)
    # 退出他人福地
    elif queryType == 4:
        PyDataManager.GetDBPyMineAreaItemManager().DelViewAreaPlayerID(playerID)
    return
def SyncMineAreaItemInfo(areaPlayerID, mineIndexList, notifyPlayerIDListEx=None):
    '''某个福地物品变更时同步,会同步给相关玩家
    @param areaPlayerID: 福地玩家ID,可能是假人
    @param mineIndexList: 需要同步的矿物索引
    @param notifyPlayerIDListEx: 额外需要通知的玩家ID列表
    '''
    if not mineIndexList:
        return
    notifyPlayerIDList = [] # 同步给相关的玩家,默认包含自己
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    # 自己,假人不用
    if areaPlayerID > Def_FakeAreaCount:
        notifyPlayerIDList.append(areaPlayerID)
    # 列表中
    for playerID, socialIDList in mineItemMgr.socialIDListDict.items():
        if areaPlayerID in socialIDList:
            notifyPlayerIDList.append(playerID)
    for playerID, neighborIDList in mineItemMgr.neighborIDListDict.items():
        if areaPlayerID in neighborIDList:
            notifyPlayerIDList.append(playerID)
    # 抢劫中
    for index in mineIndexList:
        mineItemData = mineItemMgr.GetMineItem(areaPlayerID, index)
        if mineItemData.RobPlayerID:
            notifyPlayerIDList.append(mineItemData.RobPlayerID)
    # 查看中
    if areaPlayerID in mineItemMgr.viewAreaPlayerIDDict:
        notifyPlayerIDList += mineItemMgr.viewAreaPlayerIDDict[areaPlayerID]
    # 额外的
    if notifyPlayerIDListEx:
        notifyPlayerIDList += notifyPlayerIDListEx
    if not notifyPlayerIDList:
        return
    clientPack = __GetMineAreaInfoPack([[areaPlayerID, mineIndexList]])
    # 去重同步
    playerManager = GameWorld.GetPlayerManager()
    for playerID in set(notifyPlayerIDList):
        if playerID <= Def_FakeAreaCount:
            continue
        curPlayer = playerManager.FindPlayerByID(playerID)
        if curPlayer == None or not curPlayer.GetInitOK():
            continue
        if PlayerControl.GetIsTJG(curPlayer):
            continue
        NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
def SyncSocialAreaInfo(curPlayer, queryType=0, queryValue=0):
    ## 同步有关系的道友福地列表
    playerID = curPlayer.GetPlayerID()
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    if playerID in mineItemMgr.socialIDListDict:
        socialIDList = mineItemMgr.socialIDListDict[playerID]
    else:
        socialIDList = __DoUpdSocialPlayerIDList(playerID)
    areaMineList = [[areaPlayerID, []] for areaPlayerID in socialIDList]
    clientPack = __GetMineAreaInfoPack(areaMineList, queryType, queryValue)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
def SyncNeighborAreaInfo(curPlayer, tick, queryType=0, queryValue=0):
    ## 同步周围随机福地列表
    playerID = curPlayer.GetPlayerID()
    isRefresh = queryValue
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    neighborIDList = mineItemMgr.neighborIDListDict.get(playerID, [])
    neighborIDListBef = neighborIDList
    if isRefresh:
        refreshCD = IpyGameDataPY.GetFuncCfg("MineAreaRob", 3) * 1000
        if refreshCD:
            if tick - curPlayer.GetDictByKey(NeighborAreaRefreshTick) < refreshCD:
                GameWorld.Log("周围随机福地刷新CD中!", playerID)
                return
            curPlayer.SetDict(NeighborAreaRefreshTick, tick)
        neighborIDList = [] # 置空重新随机
    else:
        neighborIDList = mineItemMgr.neighborIDListDict.get(playerID, [])
    if not neighborIDList:
        random.shuffle(mineItemMgr.realAreaPlayerIDList)
        random.shuffle(mineItemMgr.fackAreaPlayerIDList)
        areaPlayerIDList = mineItemMgr.realAreaPlayerIDList + mineItemMgr.fackAreaPlayerIDList
        if playerID in areaPlayerIDList:
            areaPlayerIDList.remove(playerID)
        for neighborIDBef in neighborIDListBef: # 之前的先不随机
            if neighborIDBef in areaPlayerIDList:
                areaPlayerIDList.remove(neighborIDBef)
        neighborCount = IpyGameDataPY.GetFuncCfg("MineAreaRob", 2)
        neighborIDList = areaPlayerIDList[:neighborCount]
        mineItemMgr.neighborIDListDict[playerID] = neighborIDList
        GameWorld.DebugLog("刷新周围随机福地: %s" % neighborIDList, playerID)
    areaMineList = [[areaPlayerID, []] for areaPlayerID in neighborIDList]
    clientPack = __GetMineAreaInfoPack(areaMineList, queryType, queryValue)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
def SyncPullingAreaMineInfo(curPlayer):
    ## 同步拉取中的物品信息,仅登录时主动同步一次
    playerID = curPlayer.GetPlayerID()
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    if playerID not in mineItemMgr.pullingItemListDict:
        return
    pullingItemList = mineItemMgr.pullingItemListDict[playerID]
    if not pullingItemList:
        return
    pullIndexDict = {}
    for mineItemData in pullingItemList:
        areaPlayerID = mineItemData.PlayerID
        if areaPlayerID not in pullIndexDict:
            pullIndexDict[areaPlayerID] = []
        indexList = pullIndexDict[areaPlayerID]
        indexList.append(mineItemData.Index)
    areaMineList = []
    for areaPlayerID, indexList in pullIndexDict.items():
        areaMineList.append([areaPlayerID, indexList])
    clientPack = __GetMineAreaInfoPack(areaMineList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
def __GetMineAreaInfoPack(areaMineList, queryType=0, queryValue=0):
    ''' 获取同步福地详细信息包
    @param areaMineList: [[areaPlayerID, mineIndexList], ...] 按指定福地ID顺序列表获取,mineIndexList为空时同步该福地全部物品,否则只同步指定索引物品
    '''
    mineItemMgr = PyDataManager.GetDBPyMineAreaItemManager()
    clientPack = ChPyNetSendPack.tagGCMineAreaInfo()
    clientPack.QueryType = queryType
    clientPack.QueryValue = queryValue
    clientPack.AreaList = []
    for areaPlayerID, mineIndexList in areaMineList:
        areaInfo = ChPyNetSendPack.tagGCMineArea()
        areaInfo.PlayerID = areaPlayerID
        if areaPlayerID > Def_FakeAreaCount:
            cacheDict = PlayerViewCache.GetCachePropDataDict(PlayerViewCache.FindViewCache(areaPlayerID))
            areaInfo.PlayerName = cacheDict.get("Name", "")
            areaInfo.Face = cacheDict.get("Face", 0)
        areaInfo.MineItemList = []
        if not mineIndexList:
            mineIndexList = range(IpyGameDataPY.GetFuncCfg("MineAreaBase", 1))
        for index in mineIndexList:
            mineItemData = mineItemMgr.GetMineItem(areaPlayerID, index)
            mineItem = ChPyNetSendPack.tagGCMineItem()
            mineItem.Index = index
            mineItem.MineID = mineItemData.MineID
            mineItem.MineType = mineItemData.MineType
            mineItem.UpdTime = mineItemData.UpdTime
            mineItem.Position = mineItemData.Position
            mineItem.PosLen = len(mineItem.Position)
            mineItem.MoveSpeed = "%s" % getattr(mineItemData, MineItemAttr_MoveSpeed)
            mineItem.SpeedLen = len(mineItem.MoveSpeed)
            mineItem.EndTime = getattr(mineItemData, MineItemAttr_EndTime)
            mineItem.WorkerCount = mineItemData.WorkerCount
            mineItem.RobPlayerID = mineItemData.RobPlayerID
            mineItem.RobWorkerCount = mineItemData.RobWorkerCount
            if mineItemData.RobPlayerID:
                robCacheDict = PlayerViewCache.GetCachePropDataDict(PlayerViewCache.FindViewCache(mineItemData.RobPlayerID))
                mineItem.RobPlayerName = robCacheDict.get("Name", "")
                mineItem.RobFace = robCacheDict.get("Face", 0)
            areaInfo.MineItemList.append(mineItem)
        areaInfo.MineCount = len(areaInfo.MineItemList)
        clientPack.AreaList.append(areaInfo)
    clientPack.AreaCount = len(clientPack.AreaList)
    return clientPack
#// B0 34 福地请求结算奖励 #tagCGMineAreaAwardGet
#
#struct    tagCGMineAreaAwardGet
#{
#    tagHead        Head;
#};
def OnMineAreaAwardGet(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    if tick - curPlayer.GetDictByKey(MineAreaAwardGetTick) < 10000:
        GameWorld.DebugLog("结算福地奖励请求CD中!", playerID)
        return
    awardMgr = PyDataManager.GetDBPyMineAreaAwardManager()
    awardDict = awardMgr.playerAreaAwardDict.get(playerID, {})
    if not awardDict:
        GameWorld.DebugLog("当前福地玩家没有待领取奖励!", playerID)
        return
    awardItemDict = {}
    awardInfoList = []
    for GUID, awardData in awardDict.items():
        mineID = awardData.MineID
        awardTime = awardData.AwardTime
        workerCount = awardData.WorkerCount
        areaPlayerID = awardData.AreaPlayerID
        ipyData = IpyGameDataPY.GetIpyGameData("MineAreaItem", mineID)
        if not ipyData:
            continue
        itemID = ipyData.GetItemID()
        itemCount = ipyData.GetItemCount()
        itemLV = ipyData.GetItemLV()
        awardItemDict[itemID] = awardItemDict.get(itemID, 0) + itemCount
        awardInfoList.append([GUID, awardTime, workerCount, areaPlayerID, mineID, itemLV, itemID, itemCount])
    # 通知地图玩家给物品
    curPlayer.SetDict(MineAreaAwardGetTick, tick)
    MapServer_QueryPlayerResult(curPlayer, "MineAreaAwardGet", [awardInfoList])
    return
def __DoMineAreaAwardGetOK(curPlayer, dataMsg):
    playerID = curPlayer.GetPlayerID()
    GUIDList, awardItemList = dataMsg
    curPlayer.SetDict(MineAreaAwardGetTick, 0)
    awardMgr = PyDataManager.GetDBPyMineAreaAwardManager()
    awardDict = awardMgr.playerAreaAwardDict.get(playerID, {})
    if not awardDict:
        return
    for GUID in GUIDList:
        awardDict.pop(GUID, None)
    SyncMineAwardAward(curPlayer, 1, awardItemList)
    return
def SyncMineAwardAward(curPlayer, awardType=0, awardItemList=None):
    # @param awardType: 0-通知有奖励,前端下次进入福地可请求进行结算;1-结算奖励结果通知
    # @param awardItemList: 奖励信息 [[物品ID,个数,是否拍品], ...]
    clientPack = ChPyNetSendPack.tagGCMineAreaAwardInfo()
    clientPack.AwardType = awardType
    if awardItemList:
        clientPack.AwardInfo = str(awardItemList)
    clientPack.AwardLen = len(clientPack.AwardInfo)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
def MapServer_QueryPlayerResult(curPlayer, queryType, queryData, ret=1):
    resultMsg = str([queryType, queryData, ret])
    curPlayer.MapServer_QueryPlayerResult(0, 0, "MineArea", resultMsg, len(resultMsg))
    GameWorld.Log("福地发送MapServer: %s" % resultMsg, curPlayer.GetPlayerID())
    return
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
@@ -112,6 +112,7 @@
import GameWorldOpenServerCampaign
import CrossBillboard
import CrossChampionship
import GameWorldMineArea
#---------------------------------------------------------------------
#---------------------------------------------------------------------
@@ -326,6 +327,9 @@
    #情缘
    PlayerLove.OnTimeProcess(curTime, tick)
    
    #福地
    GameWorldMineArea.OnMineItemTimeProcess(curTime, tick)
    #每整分钟处理一次
    curDateTime = datetime.datetime.today()
    curMinute = curDateTime.minute
@@ -384,6 +388,8 @@
    PlayerFamilyRedPacket.OnRedPacketMinuteProcess()
    #拍卖行
    AuctionHouse.OnAuctionItemMinuteProcess(tick)
    #福地
    GameWorldMineArea.OnProcessOnMinute()
    #每5分钟触发一次仙盟总战力更新
    if curMinute % 5 == 0:
        PlayerFamily.UpdFamilyTotalFightPower()
ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -74,6 +74,7 @@
import CrossBattlefield
import CrossActAllRecharge
import CrossYaomoBoss
import GameWorldMineArea
#---------------------------------------------------------------------
#---------------------------------------------------------------------
@@ -205,6 +206,8 @@
        PlayerAssist.OnPlayerLogin(curPlayer)
        #天星塔
        GameWorldSkyTower.OnPlayerLogin(curPlayer)
        #福地
        GameWorldMineArea.OnPlayerLogin(curPlayer)
        GMT_CTG.OnPlayerLogin(curPlayer)
        
    else:
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
@@ -31,6 +31,7 @@
import IPY_GameServer
import PlayerDBGSEvent
import CrossChampionship
import GameWorldMineArea
import IpyGameDataPY
import CrossRealmMsg
import ShareDefine
@@ -437,6 +438,7 @@
    playerID = curPlayer.GetPlayerID()
    FuncOpenLogicDict = {
                         ShareDefine.GameFuncID_Championship:lambda curObj:CrossChampionship.DoChampionshipOpen(curObj),
                         ShareDefine.GameFuncID_MineArea:lambda curObj:GameWorldMineArea.DoMineAreaFuncOpen(curObj),
                         }
    for funcID in funcIDList:
        if funcID in FuncOpenLogicDict:
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -81,6 +81,7 @@
import AuctionHouse
import PlayerFairyDomain
import GameWorldSkyTower
import GameWorldMineArea
import GameWorldArena
import GameWorldItem
import PlayerAssist
@@ -1025,6 +1026,16 @@
            return
        resultName = '%s' % ret
        
    # 福地
    if callName =="MineArea":
        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
        if not curPlayer:
            return
        ret = GameWorldMineArea.MapServer_MineArea(curPlayer, eval(resultName))
        if ret == None:
            return
        resultName = '%s' % ret
    # 天星塔
    if callName == "SkyTower":
        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
@@ -147,6 +147,8 @@
def GetCachePropDataDict(curCache):
    ## 获取缓存基础属性字典信息
    if not curCache:
        return {}
    if not hasattr(curCache, "PropDataDict"):
        curCache.PropDataDict = {}
    if not curCache.PropDataDict and curCache.PropData:
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
@@ -26,6 +26,7 @@
import CrossRealmPK
import AuctionHouse
import PlayerAssist
import GameWorldMineArea
import PyGameDataStruct
import IpyGameDataPY
import PlayerCharm
@@ -309,6 +310,9 @@
class PyGameDataManager(object):
    def __init__(self):
        self.DBPyMineAreaAwardManager = GameWorldMineArea.DBPyMineAreaAwardManager()
        self.DBPyMineAreaRecordManager = GameWorldMineArea.DBPyMineAreaRecordManager()
        self.DBPyMineAreaItemManager = GameWorldMineArea.DBPyMineAreaItemManager()
        self.DBPyCoupleManager = PlayerLove.DBPyCoupleManager()
        self.DBPyUnNotifyLoveGiftRecManager = PlayerLove.DBPyUnNotifyLoveGiftRecManager()
        self.DBPyCharmValueRecManager = PlayerCharm.DBPyCharmValueRecManager()
@@ -338,6 +342,9 @@
    def GetSaveData(self):
        buff = ""
        buff += self.DBPyMineAreaAwardManager.GetSaveData()
        buff += self.DBPyMineAreaRecordManager.GetSaveData()
        buff += self.DBPyMineAreaItemManager.GetSaveData()
        buff += self.DBPyCoupleManager.GetSaveData()
        buff += self.DBPyUnNotifyLoveGiftRecManager.GetSaveData()
        buff += self.DBPyCharmValueRecManager.GetSaveData()
@@ -366,6 +373,9 @@
        return buff
    
    def LoadGameData(self, gameBuffer, pos):
        pos = self.DBPyMineAreaAwardManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        pos = self.DBPyMineAreaRecordManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        pos = self.DBPyMineAreaItemManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        pos = self.DBPyCoupleManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        pos = self.DBPyUnNotifyLoveGiftRecManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        pos = self.DBPyCharmValueRecManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
@@ -481,6 +491,21 @@
    pyGameDataMgr = GetPyGameDataManager()
    return pyGameDataMgr.familyStoreItemManager
def GetDBPyMineAreaAwardManager():
    # 福地奖励结算管理
    pyGameDataMgr = GetPyGameDataManager()
    return pyGameDataMgr.DBPyMineAreaAwardManager
def GetDBPyMineAreaRecordManager():
    # 福地矿物记录管理
    pyGameDataMgr = GetPyGameDataManager()
    return pyGameDataMgr.DBPyMineAreaRecordManager
def GetDBPyMineAreaItemManager():
    # 福地矿物管理
    pyGameDataMgr = GetPyGameDataManager()
    return pyGameDataMgr.DBPyMineAreaItemManager
def GetDBPyCoupleManager():
    # 伴侣管理
    pyGameDataMgr = GetPyGameDataManager()
ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
@@ -2618,4 +2618,303 @@
                self.ADOResult,
            )
        return output
# 福地矿物表 #tagDBPyMineAreaItem
class tagDBPyMineAreaItem(Structure):
    _pack_ = 1
    _fields_ = [
        ('PlayerID', ctypes.c_ulong),
        ('Index', ctypes.c_ubyte),
        ('MineID', ctypes.c_ushort),
        ('MineType', ctypes.c_ubyte),
        ('UpdTime', ctypes.c_ulong),
        ('PosLen', ctypes.c_ubyte),
        ('Position', ctypes.c_char_p),
        ('WorkerCount', ctypes.c_ubyte),
        ('WorkerState', ctypes.c_ubyte),
        ('RobPlayerID', ctypes.c_ulong),
        ('RobWorkerCount', ctypes.c_ubyte),
        ('RobWorkerState', ctypes.c_ubyte),
        ('ADOResult', ctypes.c_ulong),
    ]
    def __init__(self):
        Structure.__init__(self)
        self.clear()
    def clear(self):
        self.PlayerID = 0
        self.Index = 0
        self.MineID = 0
        self.MineType = 0
        self.UpdTime = 0
        self.PosLen = 0
        self.Position = ''
        self.WorkerCount = 0
        self.WorkerState = 0
        self.RobPlayerID = 0
        self.RobWorkerCount = 0
        self.RobWorkerState = 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.Index, pos = CommFunc.ReadBYTE(buf, pos)
        self.MineID, pos = CommFunc.ReadWORD(buf, pos)
        self.MineType, pos = CommFunc.ReadBYTE(buf, pos)
        self.UpdTime, pos = CommFunc.ReadDWORD(buf, pos)
        self.PosLen, pos = CommFunc.ReadBYTE(buf, pos)
        tmp, pos = CommFunc.ReadString(buf, pos, self.PosLen)
        self.Position = ctypes.c_char_p(tmp)
        self.WorkerCount, pos = CommFunc.ReadBYTE(buf, pos)
        self.WorkerState, pos = CommFunc.ReadBYTE(buf, pos)
        self.RobPlayerID, pos = CommFunc.ReadDWORD(buf, pos)
        self.RobWorkerCount, pos = CommFunc.ReadBYTE(buf, pos)
        self.RobWorkerState, pos = CommFunc.ReadBYTE(buf, pos)
        return self.getLength()
    def getBuffer(self):
        buf = ''
        buf = CommFunc.WriteDWORD(buf, self.PlayerID)
        buf = CommFunc.WriteBYTE(buf, self.Index)
        buf = CommFunc.WriteWORD(buf, self.MineID)
        buf = CommFunc.WriteBYTE(buf, self.MineType)
        buf = CommFunc.WriteDWORD(buf, self.UpdTime)
        buf = CommFunc.WriteBYTE(buf, self.PosLen)
        buf = CommFunc.WriteString(buf, self.PosLen, self.Position)
        buf = CommFunc.WriteBYTE(buf, self.WorkerCount)
        buf = CommFunc.WriteBYTE(buf, self.WorkerState)
        buf = CommFunc.WriteDWORD(buf, self.RobPlayerID)
        buf = CommFunc.WriteBYTE(buf, self.RobWorkerCount)
        buf = CommFunc.WriteBYTE(buf, self.RobWorkerState)
        return buf
    def getLength(self):
        length = 0
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_ushort)
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ubyte)
        length += self.PosLen
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_ubyte)
        return length
    def outputString(self):
        output = '''// 福地矿物表 #tagDBPyMineAreaItem:
            PlayerID = %s,
            Index = %s,
            MineID = %s,
            MineType = %s,
            UpdTime = %s,
            PosLen = %s,
            Position = %s,
            WorkerCount = %s,
            WorkerState = %s,
            RobPlayerID = %s,
            RobWorkerCount = %s,
            RobWorkerState = %s,
            ADOResult = %s,
            '''%(
                self.PlayerID,
                self.Index,
                self.MineID,
                self.MineType,
                self.UpdTime,
                self.PosLen,
                self.Position,
                self.WorkerCount,
                self.WorkerState,
                self.RobPlayerID,
                self.RobWorkerCount,
                self.RobWorkerState,
                self.ADOResult,
            )
        return output
# 福地记录表 #tagDBPyMineAreaRecord
class tagDBPyMineAreaRecord(Structure):
    _pack_ = 1
    _fields_ = [
        ('PlayerID', ctypes.c_ulong),
        ('RecordType', ctypes.c_ulong),
        ('TagPlayerID', ctypes.c_ulong),
        ('RecordTime', ctypes.c_ulong),
        ('MineID', ctypes.c_ushort),
        ('DataLen', ctypes.c_ushort),
        ('Data', ctypes.c_char_p),
        ('ADOResult', ctypes.c_ulong),
    ]
    def __init__(self):
        Structure.__init__(self)
        self.clear()
    def clear(self):
        self.PlayerID = 0
        self.RecordType = 0
        self.TagPlayerID = 0
        self.RecordTime = 0
        self.MineID = 0
        self.DataLen = 0
        self.Data = ''
    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.RecordType, pos = CommFunc.ReadDWORD(buf, pos)
        self.TagPlayerID, pos = CommFunc.ReadDWORD(buf, pos)
        self.RecordTime, pos = CommFunc.ReadDWORD(buf, pos)
        self.MineID, pos = CommFunc.ReadWORD(buf, pos)
        self.DataLen, pos = CommFunc.ReadWORD(buf, pos)
        tmp, pos = CommFunc.ReadString(buf, pos, self.DataLen)
        self.Data = ctypes.c_char_p(tmp)
        return self.getLength()
    def getBuffer(self):
        buf = ''
        buf = CommFunc.WriteDWORD(buf, self.PlayerID)
        buf = CommFunc.WriteDWORD(buf, self.RecordType)
        buf = CommFunc.WriteDWORD(buf, self.TagPlayerID)
        buf = CommFunc.WriteDWORD(buf, self.RecordTime)
        buf = CommFunc.WriteWORD(buf, self.MineID)
        buf = CommFunc.WriteWORD(buf, self.DataLen)
        buf = CommFunc.WriteString(buf, self.DataLen, self.Data)
        return buf
    def getLength(self):
        length = 0
        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 += sizeof(ctypes.c_ushort)
        length += self.DataLen
        return length
    def outputString(self):
        output = '''// 福地记录表 #tagDBPyMineAreaRecord:
            PlayerID = %s,
            RecordType = %s,
            TagPlayerID = %s,
            RecordTime = %s,
            MineID = %s,
            DataLen = %s,
            Data = %s,
            ADOResult = %s,
            '''%(
                self.PlayerID,
                self.RecordType,
                self.TagPlayerID,
                self.RecordTime,
                self.MineID,
                self.DataLen,
                self.Data,
                self.ADOResult,
            )
        return output
# 福地结算奖励表 #tagDBPyMineAreaAward
class tagDBPyMineAreaAward(Structure):
    _pack_ = 1
    _fields_ = [
        ('GUIDLen', ctypes.c_ubyte),
        ('GUID', ctypes.c_char_p),
        ('PlayerID', ctypes.c_ulong),
        ('AwardTime', ctypes.c_ulong),
        ('MineID', ctypes.c_ushort),
        ('WorkerCount', ctypes.c_ubyte),
        ('AreaPlayerID', ctypes.c_ulong),
        ('ADOResult', ctypes.c_ulong),
    ]
    def __init__(self):
        Structure.__init__(self)
        self.clear()
    def clear(self):
        self.GUIDLen = 0
        self.GUID = ''
        self.PlayerID = 0
        self.AwardTime = 0
        self.MineID = 0
        self.WorkerCount = 0
        self.AreaPlayerID = 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.GUIDLen, pos = CommFunc.ReadBYTE(buf, pos)
        tmp, pos = CommFunc.ReadString(buf, pos, self.GUIDLen)
        self.GUID = ctypes.c_char_p(tmp)
        self.PlayerID, pos = CommFunc.ReadDWORD(buf, pos)
        self.AwardTime, pos = CommFunc.ReadDWORD(buf, pos)
        self.MineID, pos = CommFunc.ReadWORD(buf, pos)
        self.WorkerCount, pos = CommFunc.ReadBYTE(buf, pos)
        self.AreaPlayerID, pos = CommFunc.ReadDWORD(buf, pos)
        return self.getLength()
    def getBuffer(self):
        buf = ''
        buf = CommFunc.WriteBYTE(buf, self.GUIDLen)
        buf = CommFunc.WriteString(buf, self.GUIDLen, self.GUID)
        buf = CommFunc.WriteDWORD(buf, self.PlayerID)
        buf = CommFunc.WriteDWORD(buf, self.AwardTime)
        buf = CommFunc.WriteWORD(buf, self.MineID)
        buf = CommFunc.WriteBYTE(buf, self.WorkerCount)
        buf = CommFunc.WriteDWORD(buf, self.AreaPlayerID)
        return buf
    def getLength(self):
        length = 0
        length += sizeof(ctypes.c_ubyte)
        length += self.GUIDLen
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ushort)
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_ulong)
        return length
    def outputString(self):
        output = '''// 福地结算奖励表 #tagDBPyMineAreaAward:
            GUIDLen = %s,
            GUID = %s,
            PlayerID = %s,
            AwardTime = %s,
            MineID = %s,
            WorkerCount = %s,
            AreaPlayerID = %s,
            ADOResult = %s,
            '''%(
                self.GUIDLen,
                self.GUID,
                self.PlayerID,
                self.AwardTime,
                self.MineID,
                self.WorkerCount,
                self.AreaPlayerID,
                self.ADOResult,
            )
        return output
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -1188,6 +1188,7 @@
GameFuncID_FaQi = 199           # 法器
GameFuncID_LianTi = 207         # 炼体
GameFuncID_Championship = 210   # 排位
GameFuncID_MineArea = 223       # 福地
# 以下为暂时无用的
GameFuncID_Truck = 33           # 运镖
GameFuncID_RunDaily = 34        # 日常跑环
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -2117,6 +2117,110 @@
#------------------------------------------------------
# B0 34 福地请求结算奖励 #tagCGMineAreaAwardGet
class  tagCGMineAreaAwardGet(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        self.SubCmd = 0x34
        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 = 0xB0
        self.SubCmd = 0x34
        return
    def GetLength(self):
        return sizeof(tagCGMineAreaAwardGet)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 34 福地请求结算奖励 //tagCGMineAreaAwardGet:
                                Cmd:%s,
                                SubCmd:%s
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd
                                )
        return DumpString
m_NAtagCGMineAreaAwardGet=tagCGMineAreaAwardGet()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGMineAreaAwardGet.Cmd,m_NAtagCGMineAreaAwardGet.SubCmd))] = m_NAtagCGMineAreaAwardGet
#------------------------------------------------------
# B0 33 福地查看 #tagCGMineAreaView
class  tagCGMineAreaView(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("QueryType", c_ubyte),    # 查询同步类型:0-后端主动同步;1-查看指定福地;2-查看道友福地列表;3-查看周围随机福地列表;4-退出他人福地;
                  ("QueryValue", c_int),    # 查询值,类型1时-发送目标玩家ID;3时-发送是否重新随机
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        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 = 0xB0
        self.SubCmd = 0x33
        self.QueryType = 0
        self.QueryValue = 0
        return
    def GetLength(self):
        return sizeof(tagCGMineAreaView)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 33 福地查看 //tagCGMineAreaView:
                                Cmd:%s,
                                SubCmd:%s,
                                QueryType:%d,
                                QueryValue:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.QueryType,
                                self.QueryValue
                                )
        return DumpString
m_NAtagCGMineAreaView=tagCGMineAreaView()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGMineAreaView.Cmd,m_NAtagCGMineAreaView.SubCmd))] = m_NAtagCGMineAreaView
#------------------------------------------------------
#B0 25 请求家族悬赏任务完成情况 #tagQueryFamilyArrestOverState
class  tagQueryFamilyArrestOverState(Structure):
@@ -17341,6 +17445,170 @@
#------------------------------------------------------
# B0 30 福地物品拉 #tagCMMineItemPull
class  tagCMMineItemPull(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("PlayerID", c_int),    # 福地所属玩家ID,0默认自己
                  ("ItemIndex", c_ubyte),    # 物品所在位置索引0~n
                  ("WorkerCount", c_ubyte),    # 上工人人数
                  ("IsPreview", c_ubyte),    # 是否预览;0-直接拉,1-预览大概时间
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        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 = 0xB0
        self.SubCmd = 0x30
        self.PlayerID = 0
        self.ItemIndex = 0
        self.WorkerCount = 0
        self.IsPreview = 0
        return
    def GetLength(self):
        return sizeof(tagCMMineItemPull)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 30 福地物品拉 //tagCMMineItemPull:
                                Cmd:%s,
                                SubCmd:%s,
                                PlayerID:%d,
                                ItemIndex:%d,
                                WorkerCount:%d,
                                IsPreview:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.PlayerID,
                                self.ItemIndex,
                                self.WorkerCount,
                                self.IsPreview
                                )
        return DumpString
m_NAtagCMMineItemPull=tagCMMineItemPull()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMMineItemPull.Cmd,m_NAtagCMMineItemPull.SubCmd))] = m_NAtagCMMineItemPull
#------------------------------------------------------
# B0 31 福地物品刷新 #tagCMMineItemRefresh
class  tagCMMineItemRefresh(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("IsSuper", c_ubyte),    # 是否超级刷新
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        self.SubCmd = 0x31
        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 = 0xB0
        self.SubCmd = 0x31
        self.IsSuper = 0
        return
    def GetLength(self):
        return sizeof(tagCMMineItemRefresh)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 31 福地物品刷新 //tagCMMineItemRefresh:
                                Cmd:%s,
                                SubCmd:%s,
                                IsSuper:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.IsSuper
                                )
        return DumpString
m_NAtagCMMineItemRefresh=tagCMMineItemRefresh()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMMineItemRefresh.Cmd,m_NAtagCMMineItemRefresh.SubCmd))] = m_NAtagCMMineItemRefresh
#------------------------------------------------------
# B0 32 福地工人雇佣 #tagCMMineWorkerEmploy
class  tagCMMineWorkerEmploy(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        self.SubCmd = 0x32
        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 = 0xB0
        self.SubCmd = 0x32
        return
    def GetLength(self):
        return sizeof(tagCMMineWorkerEmploy)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 32 福地工人雇佣 //tagCMMineWorkerEmploy:
                                Cmd:%s,
                                SubCmd:%s
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd
                                )
        return DumpString
m_NAtagCMMineWorkerEmploy=tagCMMineWorkerEmploy()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMMineWorkerEmploy.Cmd,m_NAtagCMMineWorkerEmploy.SubCmd))] = m_NAtagCMMineWorkerEmploy
#------------------------------------------------------
#B0 26 请求家族悬赏奖励领取情况 #tagQueryFamilyArrestAwardReceiveState
class  tagQueryFamilyArrestAwardReceiveState(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -7722,6 +7722,424 @@
#------------------------------------------------------
# B0 34 福地结算奖励信息 #tagGCMineAreaAwardInfo
class  tagGCMineAreaAwardInfo(Structure):
    Head = tagHead()
    AwardType = 0    #(BYTE AwardType)// 0-通知有奖励,前端下次进入福地可请求进行结算;1-结算奖励结果通知
    AwardLen = 0    #(BYTE AwardLen)
    AwardInfo = ""    #(String AwardInfo)//奖励信息 [物品ID,个数,是否拍品], ...]
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x34
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.AwardType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.AwardLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.AwardInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.AwardLen)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x34
        self.AwardType = 0
        self.AwardLen = 0
        self.AwardInfo = ""
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 1
        length += len(self.AwardInfo)
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.AwardType)
        data = CommFunc.WriteBYTE(data, self.AwardLen)
        data = CommFunc.WriteString(data, self.AwardLen, self.AwardInfo)
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                AwardType:%d,
                                AwardLen:%d,
                                AwardInfo:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.AwardType,
                                self.AwardLen,
                                self.AwardInfo
                                )
        return DumpString
m_NAtagGCMineAreaAwardInfo=tagGCMineAreaAwardInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCMineAreaAwardInfo.Head.Cmd,m_NAtagGCMineAreaAwardInfo.Head.SubCmd))] = m_NAtagGCMineAreaAwardInfo
#------------------------------------------------------
# B0 33 福地详细信息 #tagGCMineAreaInfo
class  tagGCMineItem(Structure):
    Index = 0    #(BYTE Index)// 矿物所在福地位置索引,0~n
    MineID = 0    #(WORD MineID)// 矿物ID,对应福地采集表中ID,0代表该索引位置没有矿物
    MineType = 0    #(BYTE MineType)// 矿物类型:0-常规;1-超级
    UpdTime = 0    #(DWORD UpdTime)// 最后一次更新时间戳
    PosLen = 0    #(BYTE PosLen)
    Position = ""    #(String Position)// 最后一次更新时所在位置百分比,0~100,支持小数,下0上100,可认为分为100格,速度为 x格/秒
    SpeedLen = 0    #(BYTE SpeedLen)
    MoveSpeed = ""    #(String MoveSpeed)// 移动速度,x格/秒,支持小数
    EndTime = 0    #(DWORD EndTime)// 拉取结束时间戳
    WorkerCount = 0    #(BYTE WorkerCount)// 工人个数,为0时代表福地玩家没有使用工人拉回
    RobPlayerID = 0    #(DWORD RobPlayerID)// 抢夺玩家ID,为0时代表没人抢夺
    RobWorkerCount = 0    #(BYTE RobWorkerCount)// 抢夺工人个数
    RobPlayerName = ""    #(char RobPlayerName[33])
    RobFace = 0    #(DWORD RobFace)
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.Index,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.MineID,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.MineType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.UpdTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.PosLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.Position,_pos = CommFunc.ReadString(_lpData, _pos,self.PosLen)
        self.SpeedLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.MoveSpeed,_pos = CommFunc.ReadString(_lpData, _pos,self.SpeedLen)
        self.EndTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.WorkerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.RobPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.RobWorkerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.RobPlayerName,_pos = CommFunc.ReadString(_lpData, _pos,33)
        self.RobFace,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        return _pos
    def Clear(self):
        self.Index = 0
        self.MineID = 0
        self.MineType = 0
        self.UpdTime = 0
        self.PosLen = 0
        self.Position = ""
        self.SpeedLen = 0
        self.MoveSpeed = ""
        self.EndTime = 0
        self.WorkerCount = 0
        self.RobPlayerID = 0
        self.RobWorkerCount = 0
        self.RobPlayerName = ""
        self.RobFace = 0
        return
    def GetLength(self):
        length = 0
        length += 1
        length += 2
        length += 1
        length += 4
        length += 1
        length += len(self.Position)
        length += 1
        length += len(self.MoveSpeed)
        length += 4
        length += 1
        length += 4
        length += 1
        length += 33
        length += 4
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteBYTE(data, self.Index)
        data = CommFunc.WriteWORD(data, self.MineID)
        data = CommFunc.WriteBYTE(data, self.MineType)
        data = CommFunc.WriteDWORD(data, self.UpdTime)
        data = CommFunc.WriteBYTE(data, self.PosLen)
        data = CommFunc.WriteString(data, self.PosLen, self.Position)
        data = CommFunc.WriteBYTE(data, self.SpeedLen)
        data = CommFunc.WriteString(data, self.SpeedLen, self.MoveSpeed)
        data = CommFunc.WriteDWORD(data, self.EndTime)
        data = CommFunc.WriteBYTE(data, self.WorkerCount)
        data = CommFunc.WriteDWORD(data, self.RobPlayerID)
        data = CommFunc.WriteBYTE(data, self.RobWorkerCount)
        data = CommFunc.WriteString(data, 33, self.RobPlayerName)
        data = CommFunc.WriteDWORD(data, self.RobFace)
        return data
    def OutputString(self):
        DumpString = '''
                                Index:%d,
                                MineID:%d,
                                MineType:%d,
                                UpdTime:%d,
                                PosLen:%d,
                                Position:%s,
                                SpeedLen:%d,
                                MoveSpeed:%s,
                                EndTime:%d,
                                WorkerCount:%d,
                                RobPlayerID:%d,
                                RobWorkerCount:%d,
                                RobPlayerName:%s,
                                RobFace:%d
                                '''\
                                %(
                                self.Index,
                                self.MineID,
                                self.MineType,
                                self.UpdTime,
                                self.PosLen,
                                self.Position,
                                self.SpeedLen,
                                self.MoveSpeed,
                                self.EndTime,
                                self.WorkerCount,
                                self.RobPlayerID,
                                self.RobWorkerCount,
                                self.RobPlayerName,
                                self.RobFace
                                )
        return DumpString
class  tagGCMineArea(Structure):
    PlayerID = 0    #(DWORD PlayerID)// 福地所属玩家ID,可能是自己或其他玩家ID,当ID小于10000时为假人
    PlayerName = ""    #(char PlayerName[33])// 可能为空,如自己或假人
    Face = 0    #(DWORD Face)
    MineCount = 0    #(BYTE MineCount)
    MineItemList = list()    #(vector<tagGCMineItem> MineItemList)// 矿物列表
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.PlayerName,_pos = CommFunc.ReadString(_lpData, _pos,33)
        self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.MineCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.MineCount):
            temMineItemList = tagGCMineItem()
            _pos = temMineItemList.ReadData(_lpData, _pos)
            self.MineItemList.append(temMineItemList)
        return _pos
    def Clear(self):
        self.PlayerID = 0
        self.PlayerName = ""
        self.Face = 0
        self.MineCount = 0
        self.MineItemList = list()
        return
    def GetLength(self):
        length = 0
        length += 4
        length += 33
        length += 4
        length += 1
        for i in range(self.MineCount):
            length += self.MineItemList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteDWORD(data, self.PlayerID)
        data = CommFunc.WriteString(data, 33, self.PlayerName)
        data = CommFunc.WriteDWORD(data, self.Face)
        data = CommFunc.WriteBYTE(data, self.MineCount)
        for i in range(self.MineCount):
            data = CommFunc.WriteString(data, self.MineItemList[i].GetLength(), self.MineItemList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                PlayerID:%d,
                                PlayerName:%s,
                                Face:%d,
                                MineCount:%d,
                                MineItemList:%s
                                '''\
                                %(
                                self.PlayerID,
                                self.PlayerName,
                                self.Face,
                                self.MineCount,
                                "..."
                                )
        return DumpString
class  tagGCMineAreaInfo(Structure):
    Head = tagHead()
    QueryType = 0    #(BYTE QueryType)// 查询同步类型:0-后端主动同步;1-查看指定福地;2-查看道友福地列表;3-查看周围随机福地列表
    QueryValue = 0    #(DWORD QueryValue)// 查询值,类型1时-发送目标玩家ID;3时-发送是否重新随机
    AreaCount = 0    #(BYTE AreaCount)
    AreaList = list()    #(vector<tagGCMineArea> AreaList)// 福地列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x33
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.QueryType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.QueryValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.AreaCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.AreaCount):
            temAreaList = tagGCMineArea()
            _pos = temAreaList.ReadData(_lpData, _pos)
            self.AreaList.append(temAreaList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x33
        self.QueryType = 0
        self.QueryValue = 0
        self.AreaCount = 0
        self.AreaList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 4
        length += 1
        for i in range(self.AreaCount):
            length += self.AreaList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.QueryType)
        data = CommFunc.WriteDWORD(data, self.QueryValue)
        data = CommFunc.WriteBYTE(data, self.AreaCount)
        for i in range(self.AreaCount):
            data = CommFunc.WriteString(data, self.AreaList[i].GetLength(), self.AreaList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                QueryType:%d,
                                QueryValue:%d,
                                AreaCount:%d,
                                AreaList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.QueryType,
                                self.QueryValue,
                                self.AreaCount,
                                "..."
                                )
        return DumpString
m_NAtagGCMineAreaInfo=tagGCMineAreaInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCMineAreaInfo.Head.Cmd,m_NAtagGCMineAreaInfo.Head.SubCmd))] = m_NAtagGCMineAreaInfo
#------------------------------------------------------
# B0 32 福地物品拉预览结果 #tagGCMineItemPullPreviewRet
class  tagGCMineItemPullPreviewRet(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("PlayerID", c_int),    # 福地所属玩家ID,0默认自己
                  ("ItemIndex", c_ubyte),    # 物品所在位置索引0~n
                  ("WorkerCount", c_ubyte),    # 上工人人数
                  ("NeedSeconds", c_int),    # 预计需要时间,秒
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB0
        self.SubCmd = 0x32
        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 = 0xB0
        self.SubCmd = 0x32
        self.PlayerID = 0
        self.ItemIndex = 0
        self.WorkerCount = 0
        self.NeedSeconds = 0
        return
    def GetLength(self):
        return sizeof(tagGCMineItemPullPreviewRet)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B0 32 福地物品拉预览结果 //tagGCMineItemPullPreviewRet:
                                Cmd:%s,
                                SubCmd:%s,
                                PlayerID:%d,
                                ItemIndex:%d,
                                WorkerCount:%d,
                                NeedSeconds:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.PlayerID,
                                self.ItemIndex,
                                self.WorkerCount,
                                self.NeedSeconds
                                )
        return DumpString
m_NAtagGCMineItemPullPreviewRet=tagGCMineItemPullPreviewRet()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCMineItemPullPreviewRet.Cmd,m_NAtagGCMineItemPullPreviewRet.SubCmd))] = m_NAtagGCMineItemPullPreviewRet
#------------------------------------------------------
# B0 04 使用协助感谢礼盒预览 #tagGCUseAssistThanksGiftPreview
class  tagGCAssistPlayerInfo(Structure):
@@ -44010,6 +44428,121 @@
#------------------------------------------------------
# B0 30 玩家福地相关信息 #tagMCPlayerMineAreaInfo
class  tagMCPlayerMineAreaInfo(Structure):
    Head = tagHead()
    WorkerCount = 0    #(BYTE WorkerCount)// 已雇佣工人数
    EnergyUsed = 0    #(WORD EnergyUsed)// 今日已消耗体力
    RefreshCount = 0    #(DWORD RefreshCount)// 今日福地刷新物品次数 - 普通刷新
    RefreshCountSuper = 0    #(BYTE RefreshCountSuper)// 今日福地刷新物品次数 - 超级刷新
    TreasureCount = 0    #(BYTE TreasureCount)// 聚宝盆类型个数,对应类型 0~n
    TreasureState = list()    #(vector<BYTE> TreasureState)// 聚宝盆是否已激活列表,[类型0是否已激活, ...]
    TreasureAward = list()    #(vector<BYTE> TreasureAward)// 聚宝盆奖励是否已领取列表,[类型0是否已领取, ...]
    TreasureProgress = list()    #(vector<BYTE> TreasureProgress)// 聚宝盆进度值列表,[类型0进度值, ...],满进度100
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x30
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.WorkerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.EnergyUsed,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.RefreshCount,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.RefreshCountSuper,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.TreasureCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.TreasureCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.TreasureState.append(value)
        for i in range(self.TreasureCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.TreasureAward.append(value)
        for i in range(self.TreasureCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.TreasureProgress.append(value)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB0
        self.Head.SubCmd = 0x30
        self.WorkerCount = 0
        self.EnergyUsed = 0
        self.RefreshCount = 0
        self.RefreshCountSuper = 0
        self.TreasureCount = 0
        self.TreasureState = list()
        self.TreasureAward = list()
        self.TreasureProgress = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 2
        length += 4
        length += 1
        length += 1
        length += 1 * self.TreasureCount
        length += 1 * self.TreasureCount
        length += 1 * self.TreasureCount
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.WorkerCount)
        data = CommFunc.WriteWORD(data, self.EnergyUsed)
        data = CommFunc.WriteDWORD(data, self.RefreshCount)
        data = CommFunc.WriteBYTE(data, self.RefreshCountSuper)
        data = CommFunc.WriteBYTE(data, self.TreasureCount)
        for i in range(self.TreasureCount):
            data = CommFunc.WriteBYTE(data, self.TreasureState[i])
        for i in range(self.TreasureCount):
            data = CommFunc.WriteBYTE(data, self.TreasureAward[i])
        for i in range(self.TreasureCount):
            data = CommFunc.WriteBYTE(data, self.TreasureProgress[i])
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                WorkerCount:%d,
                                EnergyUsed:%d,
                                RefreshCount:%d,
                                RefreshCountSuper:%d,
                                TreasureCount:%d,
                                TreasureState:%s,
                                TreasureAward:%s,
                                TreasureProgress:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.WorkerCount,
                                self.EnergyUsed,
                                self.RefreshCount,
                                self.RefreshCountSuper,
                                self.TreasureCount,
                                "...",
                                "...",
                                "..."
                                )
        return DumpString
m_NAtagMCPlayerMineAreaInfo=tagMCPlayerMineAreaInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCPlayerMineAreaInfo.Head.Cmd,m_NAtagMCPlayerMineAreaInfo.Head.SubCmd))] = m_NAtagMCPlayerMineAreaInfo
#------------------------------------------------------
# B0 07 今日协助活跃令信息 #tagMCTodayAssistMoneyInfo
class  tagMCTodayAssistMoneyInfo(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MineArea.py
New file
@@ -0,0 +1,80 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GM.Commands.MineArea
#
# @todo:福地
# @author hxp
# @date 2024-03-07
# @version 1.0
#
# 详细描述: 福地
#
#-------------------------------------------------------------------------------
#"""Version = 2024-03-07 19:30"""
#-------------------------------------------------------------------------------
import GameWorld
import PlayerControl
import PlayerMineArea
import ChConfig
## GM命令执行入口
#  @param curPlayer 当前玩家
#  @param msgList 参数列表 [addSkillID]
#  @return None
#  @remarks 函数详细说明.
def OnExec(curPlayer, msgList):
    # @return: 是否发送到GameServer
    if not msgList:
        GameWorld.DebugAnswer(curPlayer, "---------- 福地命令 ----------")
        GameWorld.DebugAnswer(curPlayer, "重置福地玩家: MineArea 0")
        GameWorld.DebugAnswer(curPlayer, "设置已用精力: MineArea e 精力")
        GameWorld.DebugAnswer(curPlayer, "设置工人数量: MineArea w 数量")
        GameWorld.DebugAnswer(curPlayer, "设置刷新次数: MineArea r 次数 [是否超级]")
        GameWorld.DebugAnswer(curPlayer, "设置聚宝进度: MineArea t 类型 进度值")
        return True
    value1 = msgList[0]
    if value1 == 0:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineWorkerCount, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineWorkerEnergyUsed, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineRefreshCount % 0, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineRefreshCount % 1, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineTreasureState, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineTreasureAward, 0)
        for treasureType in range(10):
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineTreasureProgess % treasureType, 0)
        GameWorld.DebugAnswer(curPlayer, "重置福地玩家")
    elif value1 == "e":
        energyUsed = msgList[1] if len(msgList) > 1 else 0
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineWorkerEnergyUsed, energyUsed)
        GameWorld.DebugAnswer(curPlayer, "设置已用精力: %s" % energyUsed)
    elif value1 == "w":
        workerCount = msgList[1] if len(msgList) > 1 else 0
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineWorkerCount, workerCount)
        GameWorld.DebugAnswer(curPlayer, "设置工人数量: %s" % workerCount)
    elif value1 == "r":
        refreshCount = msgList[1] if len(msgList) > 1 else 0
        isSuper = msgList[2] if len(msgList) > 2 else 0
        refreshType = 1 if isSuper else 0
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineRefreshCount % refreshType, refreshCount)
        GameWorld.DebugAnswer(curPlayer, "设置刷新次数: %s, isSuper=%s" % (refreshCount, isSuper))
    elif value1 == "t":
        treasureType = msgList[1] if len(msgList) > 1 else 0
        setProgress = msgList[2] if len(msgList) > 2 else 0
        setProgress = min(setProgress, PlayerMineArea.MineTreasureProgressMax)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineTreasureProgess % treasureType, setProgress)
        GameWorld.DebugAnswer(curPlayer, "设置聚宝进度: Type:%s,进度=%s" % (treasureType, setProgress))
    else:
        return True
    PlayerMineArea.SyncPlayerMineAreaInfo(curPlayer)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py
@@ -91,7 +91,7 @@
#                     }
# 功能开启需要同步到GameServer的
FuncOpenNotifyGameServer = [ShareDefine.GameFuncID_Championship]
FuncOpenNotifyGameServer = [ShareDefine.GameFuncID_Championship, ShareDefine.GameFuncID_MineArea]
def GetFuncOpenLVIpyData(funcID): return IpyGameDataPY.GetIpyGameData("FuncOpenLV", funcID)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -129,6 +129,7 @@
import PlayerArena
import PyGameData
import PlayerTJG
import PlayerMineArea
import datetime
import time
@@ -599,6 +600,8 @@
        PlayerArena.OnDayEx(curPlayer)
        #协助
        PlayerAssist.DoPlayerOnDay(curPlayer)
        #福地
        PlayerMineArea.PlayerOnDay(curPlayer)
        #特殊时间点过天的,一般是游戏功能,此时立即同步一次跨服玩家数据
        CrossPlayerData.SendMergePlayerDataNow(curPlayer)
        
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMineArea.py
New file
@@ -0,0 +1,316 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.PlayerMineArea
#
# @todo:矿物福地
# @author hxp
# @date 2024-03-07
# @version 1.0
#
# 详细描述: 矿物福地
#
#-------------------------------------------------------------------------------
#"""Version = 2024-03-07 19:30"""
#-------------------------------------------------------------------------------
import ChConfig
import PlayerControl
import IpyGameDataPY
import IPY_GameWorld
import ChPyNetSendPack
import NetPackCommon
import ItemControler
import ItemCommon
import GameWorld
# 聚宝盆默认最大进度
MineTreasureProgressMax = 100
def OnPlayerLogin(curPlayer):
    SyncPlayerMineAreaInfo(curPlayer)
    return
def PlayerOnDay(curPlayer):
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineWorkerEnergyUsed, 0)
    for refreshType in [0, 1]:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineRefreshCount % refreshType, 0)
    SyncPlayerMineAreaInfo(curPlayer)
    return
def GetWorkerTotal(curPlayer):
    ## 获取玩家工人总数
    initCount = 0 # 起始默认工人数
    employCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineWorkerCount)
    return initCount + employCount
def GetWorkerState(curPlayer):
    ## 获取工人疲劳状态
    workerStateEnergyList = IpyGameDataPY.GetFuncEvalCfg("MineAreaWorker", 1) # 工人疲劳状态体力列表 [充沛体力, 正常, 虚弱, 枯竭],总体力=所有体力相加
    funcEnergy = 0 # 其他功能增加的体力
    stateEnergy = 0
    energyUsed = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineWorkerEnergyUsed)
    for state, energy in enumerate(workerStateEnergyList):
        if state == 0:
            energy += funcEnergy
        stateEnergy += energy
        if energyUsed <= stateEnergy:
            return state
    return len(workerStateEnergyList) - 1 # 默认最大疲劳
#// B0 30 福地物品拉 #tagCMMineItemPull
#
#struct    tagCMMineItemPull
#{
#    tagHead        Head;
#    DWORD        PlayerID;        // 福地所属玩家ID,0默认自己
#    BYTE        ItemIndex;    // 物品所在位置索引0~n
#    BYTE        WorkerCount;    // 上工人人数
#    BYTE        IsPreview;    // 是否预览;0-直接拉,1-预览大概时间
#};
def OnMineItemPull(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    areaPlayerID = clientData.PlayerID
    itemIndex = clientData.ItemIndex
    workerCount = clientData.WorkerCount
    isPreview = clientData.IsPreview
    if not areaPlayerID:
        areaPlayerID = curPlayer.GetPlayerID()
    workerTotal = GetWorkerTotal(curPlayer)
    workerState = GetWorkerState(curPlayer)
    SendToGameServer_MineArea(curPlayer, "Pull", [areaPlayerID, itemIndex, workerCount, workerState, workerTotal, isPreview])
    return
#// B0 31 福地物品刷新 #tagCMMineItemRefresh
#
#struct    tagCMMineItemRefresh
#
#{
#    tagHead        Head;
#    BYTE        IsSuper;    // 是否超级刷新
#};
def OnMineItemRefresh(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    isSuper = clientData.IsSuper
    refreshType = str(1 if isSuper else 0)
    moneyDict = IpyGameDataPY.GetFuncEvalCfg("MineAreaRefresh", 1, {})
    if refreshType not in moneyDict:
        return
    moneyType, moneyValue = moneyDict[refreshType]
    if not PlayerControl.HaveMoney(curPlayer, moneyType, moneyValue):
        return
    refreshMaxDict = IpyGameDataPY.GetFuncEvalCfg("MineAreaRefresh", 2, {})
    refreshCountMax = refreshMaxDict.get(refreshType, 0)
    refreshCountNow = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineRefreshCount % refreshType)
    if refreshCountMax and refreshCountNow >= refreshCountMax:
        GameWorld.DebugLog("福地物品刷新次数已达今日上限! isSuper=%s,refreshCountNow=%s >= %s" % (isSuper, refreshCountNow, refreshCountMax), playerID)
        return
    PlayerControl.PayMoney(curPlayer, moneyType, moneyValue, "MineItemRefresh")
    if refreshCountMax:
        refreshCountUpd = refreshCountNow + 1
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineRefreshCount % refreshType, refreshCountUpd)
        SyncPlayerMineAreaInfo(curPlayer)
    SendToGameServer_MineArea(curPlayer, "MineItemRefresh", [playerID, isSuper])
    return
#// B0 32 福地工人雇佣 #tagCMMineWorkerEmploy
#
#struct    tagCMMineWorkerEmploy
#
#{
#    tagHead        Head;
#};
def OnMineWorkerEmploy(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    employCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineWorkerCount)
    costItemCountList = IpyGameDataPY.GetFuncEvalCfg("MineAreaWorker", 3)
    if employCount >= len(costItemCountList):
        GameWorld.DebugLog("已达到福地雇佣工人数上限! employCount=%s" % employCount)
        return
    costItemCount = costItemCountList[employCount]
    costItemID = IpyGameDataPY.GetFuncCfg("MineAreaWorker", 2)
    if not costItemID:
        return
    # 支持配0不消耗个数
    if costItemCount > 0:
        costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, costItemID, costItemCount)
        lackCnt = costItemCount - bindCnt - unBindCnt
        if lackCnt > 0:
            GameWorld.DebugLog("福地雇佣工人道具不足! costItemID=%s,costItemCount=%s,bindCnt=%s,unBindCnt=%s,lackCnt=%s,已雇佣数=%s"
                               % (costItemID, costItemCount, bindCnt, unBindCnt, lackCnt, employCount))
            return
        delCnt = costItemCount
        ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, delCnt, "MineWorkerEmploy")
    updEmployCount = employCount + 1
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineWorkerCount, updEmployCount)
    SyncPlayerMineAreaInfo(curPlayer)
    GameWorld.DebugLog("福地雇佣工人! costItemID=%s,costItemCount=%s,updEmployCount=%s" % (costItemID, costItemCount, updEmployCount), playerID)
    return
def SendToGameServer_MineArea(curPlayer, msgType, dataMsg=""):
    playerID = curPlayer.GetPlayerID()
    msgList = str([msgType, dataMsg])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "MineArea", msgList, len(msgList))
    GameWorld.Log("福地发送GameServer: %s, %s" % (msgType, dataMsg), playerID)
    return
def GameServer_MineArea_DoResult(curPlayer, msgData):
    msgType, dataMsg, _ = msgData
    ## 结算奖励
    if msgType == "MineAreaAwardGet":
        awardInfoList = dataMsg[0]
        __DoGiveMineAreaAward(curPlayer, awardInfoList)
    return
def __DoGiveMineAreaAward(curPlayer, awardInfoList):
    playerID = curPlayer.GetPlayerID()
    energyUsed = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineWorkerEnergyUsed)
    addEnergyUsed = 0
    awardItemDict = {}
    robCount = 0 # 抢劫数
    GUIDList = []
    for awardInfo in awardInfoList:
        GUID, awardTime, workerCount, areaPlayerID, mineID, itemLV, itemID, itemCount = awardInfo
        isToday = GameWorld.CheckTimeIsSameServerDayEx(awardTime)
        if isToday:
            addEnergyUsed += workerCount
        if playerID != areaPlayerID:
            robCount += 1
        awardItemDict[itemID] = awardItemDict.get(itemID, 0) + itemCount
        GUIDList.append(GUID)
        GameWorld.DebugLog("结算福地奖励! areaPlayerID=%s,mineID=%s,itemLV=%s,itemID=%s,itemCount=%s,awardTime=%s,isToday=%s,workerCount=%s %s"
                           % (areaPlayerID, mineID, itemLV, itemID, itemCount, GameWorld.ChangeTimeNumToStr(awardTime), isToday, workerCount, GUID), playerID)
    if addEnergyUsed:
        energyUsed += addEnergyUsed
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineWorkerEnergyUsed, energyUsed)
        GameWorld.DebugLog("    增加福地工人已用精力! addEnergyUsed=%s,updEnergyUsed=%s" % (addEnergyUsed, energyUsed), playerID)
    if robCount:
        OnAddMineTreasureProgress(curPlayer, robCount, False)
    SyncPlayerMineAreaInfo(curPlayer)
    awardItemList = [[itemID, itemCount, 0] for itemID, itemCount in awardItemDict.items()]
    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, None, ["MineAreaAward", False, {}])
    SendToGameServer_MineArea(curPlayer, "MineAreaAwardGetOK", [GUIDList, awardItemList])
    return
def OnMineTreasureByCTGID(curPlayer, ctgID):
    ## 充值激活聚宝盆
    treasureCTGIDList = IpyGameDataPY.GetFuncEvalCfg("MineAreaTreasure", 1)
    for treasureType, ctgIDList in enumerate(treasureCTGIDList):
        if not ctgIDList or ctgID not in ctgIDList: # 配空列表的默认激活
            continue
        state = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineTreasureState)
        if state&pow(2, treasureType):
            break
        updState = state|pow(2, treasureType)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineTreasureState, updState)
        SyncPlayerMineAreaInfo(curPlayer)
        GameWorld.Log("激活福地聚宝盆: treasureType=%s,updState=%s" % (treasureType, updState), curPlayer.GetPlayerID())
        break
    return
def OnAddMineTreasureProgress(curPlayer, robCount, isNotify=True):
    ## 增加聚宝盆进度
    # @param robCount: 抢夺物品数
    if robCount <= 0:
        return
    playerID = curPlayer.GetPlayerID()
    treasureCTGIDList = IpyGameDataPY.GetFuncEvalCfg("MineAreaTreasure", 1)
    treasureAddProgressList = IpyGameDataPY.GetFuncEvalCfg("MineAreaTreasure", 2)
    treasureState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineTreasureState)
    for treasureType, addProgressSet in enumerate(treasureAddProgressList):
        ctgIDList = treasureCTGIDList[treasureType]
        isActivite = 1 if (not ctgIDList or treasureState&pow(2, treasureType)) else 0
        if not isActivite:
            continue
        curProgress = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineTreasureProgess % treasureType)
        if curProgress >= MineTreasureProgressMax:
            continue
        addProgress = addProgressSet * robCount
        updProgress = min(curProgress + addProgress, MineTreasureProgressMax)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineTreasureProgess % treasureType, updProgress)
        GameWorld.DebugLog("    增加福地聚宝盆进度: robCount=%s,treasureType=%s,curProgress=%s,addProgress=%s,updProgress=%s"
                           % (robCount, treasureType, curProgress, addProgress, updProgress), playerID)
    if isNotify:
        SyncPlayerMineAreaInfo(curPlayer)
    return
def GetMineTreasureAward(curPlayer, treasureType):
    ## 领取聚宝盆奖励
    playerID = curPlayer.GetPlayerID()
    treasureAward = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineTreasureAward)
    if treasureAward&pow(2, treasureType):
        GameWorld.DebugLog("福地聚宝盆奖励已领取过! treasureType=%s,treasureAward=%s" % (treasureType, treasureAward), playerID)
        return
    curProgress = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineTreasureProgess % treasureType)
    if curProgress < MineTreasureProgressMax:
        GameWorld.DebugLog("福地聚宝盆进度未满,无法领奖! treasureType=%s,curProgress=%s" % (treasureType, curProgress), playerID)
        return
    treasureAwardList = IpyGameDataPY.GetFuncEvalCfg("MineAreaTreasure", 3)
    if treasureType >= len(treasureAwardList):
        return
    awardItemList = treasureAwardList[treasureType]
    if not ItemControler.CheckPackSpaceEnough(curPlayer, awardItemList):
        return
    updAward = treasureAward|pow(2, treasureType)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MineTreasureAward, updAward)
    SyncPlayerMineAreaInfo(curPlayer)
    for itemID, itemCount, isAuctionItem in awardItemList:
        ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem])
    GameWorld.DebugLog("福地聚宝盆领奖! treasureType=%s,updAward=%s,awardItemList=%s" % (treasureType, updAward, awardItemList), playerID)
    return
def SyncPlayerMineAreaInfo(curPlayer):
    clientPack = ChPyNetSendPack.tagMCPlayerMineAreaInfo()
    clientPack.WorkerCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineWorkerCount)
    clientPack.EnergyUsed = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineWorkerEnergyUsed)
    clientPack.RefreshCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineRefreshCount % 0)
    clientPack.RefreshCountSuper = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineRefreshCount % 1)
    treasureState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineTreasureState)
    treasureAward = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineTreasureAward)
    treasureCTGIDList = IpyGameDataPY.GetFuncEvalCfg("MineAreaTreasure", 1)
    clientPack.TreasureCount = len(treasureCTGIDList)
    clientPack.TreasureState = [0] * clientPack.TreasureCount
    clientPack.TreasureAward = [0] * clientPack.TreasureCount
    clientPack.TreasureProgress = [0] * clientPack.TreasureCount
    for treasureType, ctgIDList in enumerate(treasureCTGIDList):
        isActivite = 1 if (not ctgIDList or treasureState&pow(2, treasureType)) else 0
        clientPack.TreasureState[treasureType] = isActivite
        clientPack.TreasureAward[treasureType] = 1 if treasureAward&pow(2, treasureType) else 0
        clientPack.TreasureProgress[treasureType] = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MineTreasureProgess % treasureType)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_MineArea.py
New file
@@ -0,0 +1,47 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.RemoteQuery.GY_Query_MineArea
#
# @todo:福地
# @author hxp
# @date 2024-03-07
# @version 1.0
#
# 详细描述: 福地
#
#-------------------------------------------------------------------------------
#"""Version = 2024-03-07 19:30"""
#-------------------------------------------------------------------------------
import GameWorld
import PlayerMineArea
#---------------------------------------------------------------------
#逻辑实现
## 请求逻辑
#  @param query_Type 请求类型
#  @param query_ID 请求的玩家ID
#  @param packCMDList 发包命令 [ ]
#  @param tick 当前时间
#  @return "True" or "False" or ""
#  @remarks 函数详细说明.
def DoLogic(query_Type, query_ID, packCMDList, tick):
    return ""
#---------------------------------------------------------------------
#执行结果
## 执行结果
#  @param curPlayer 发出请求的玩家
#  @param callFunName 功能名称
#  @param funResult 查询的结果
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def DoResult(curPlayer, callFunName, funResult, tick):
    GameWorld.DebugLog("GY_Query_MineArea DoResult %s" % str(funResult), curPlayer.GetPlayerID())
    if funResult != "":
        PlayerMineArea.GameServer_MineArea_DoResult(curPlayer, eval(funResult))
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -1188,6 +1188,7 @@
GameFuncID_FaQi = 199           # 法器
GameFuncID_LianTi = 207         # 炼体
GameFuncID_Championship = 210   # 排位
GameFuncID_MineArea = 223       # 福地
# 以下为暂时无用的
GameFuncID_Truck = 33           # 运镖
GameFuncID_RunDaily = 34        # 日常跑环