hxp
2021-11-17 ffa8a645ed6a92a3c723bbf5c7f1eb4d5425c826
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerLove.py
@@ -21,12 +21,14 @@
import ChPyNetSendPack
import PlayerCompensation
import PlayerFamilyRedPacket
import PlayerBillboard
import PyGameDataStruct
import NetPackCommon
import IpyGameDataPY
import PlayerSocial
import PlayerCharm
import ShareDefine
import PyGameData
import CommFunc
import operator
import time
@@ -58,6 +60,227 @@
        self.playerFreeEatCountDict = {} # 玩家免费吃喜糖次数 {playerID:次数, ...}
        self.fireworksCountDict = {} # 烟花次数信息 {playerID:次数, ...}
        return
class PlayerCouple():
    def __init__(self, coupleData):
        self.coupleData = coupleData # PyGameDataStruct.tagDBPyCouple()
        # 更新最大聘礼ID
        self.BridePriceMaxID = 0
        maxCount = IpyGameDataPY.IPY_Data().GetMarryCount()
        for index in range(maxCount)[::-1]:
            ipyData = IpyGameDataPY.IPY_Data().GetMarryByIndex(index)
            priceID = ipyData.GetBridePriceID()
            if self.GetBridePriceBuyCount(priceID):
                self.BridePriceMaxID = priceID
                break
        return
    def GetCoupleID(self, playerID):
        return self.coupleData.PlayerIDA if (playerID == self.coupleData.PlayerIDB) else self.coupleData.PlayerIDB
    def GetCoupleName(self, playerID): return PlayerSocial.GetSocialPlayerName(self.GetCoupleID(playerID))
    def GetCoupleJob(self, playerID): return PlayerSocial.GetSocialPlayerJob(self.GetCoupleID(playerID))
    def GetNewMarryTime(self): return self.coupleData.NewMarryTime
    def GetMarryTime(self): return self.coupleData.MarryTime
    def GetBridePriceState(self): return self.coupleData.BridePriceState
    def GetBridePriceBuyCount(self, priceID): return GameWorld.GetDataByDigitPlace(self.coupleData.BridePriceState, priceID - 1)
    def SetBridePriceBuyCount(self, priceID, buyCount):
        self.coupleData.BridePriceState = GameWorld.ChangeDataByDigitPlace(self.coupleData.BridePriceState, priceID - 1, min(buyCount, 9))
        return self.coupleData.BridePriceState
    def GetBreakRequestID(self): return self.coupleData.BreakRequestID
    def GetBreakRequestTime(self): return self.coupleData.BreakRequestTime
    def SetBreakRequestID(self, reqID):
        self.coupleData.BreakRequestID = reqID
        self.coupleData.BreakRequestTime = 0
        if reqID > 0:
            curTime = int(time.time())
            self.coupleData.BreakRequestTime = curTime
            if reqID == self.coupleData.PlayerIDA:
                self.coupleData.BreakRequestTimeA = curTime
            else:
                self.coupleData.BreakRequestTimeB = curTime
        return
    def GetPlayerBreakRequestTime(self, playerID):
        return self.coupleData.BreakRequestTimeA if (playerID == self.coupleData.PlayerIDA) else self.coupleData.BreakRequestTimeB
    def GetSendMapServerCoupleInfo(self, playerID):
        coupleID = self.GetCoupleID(playerID)
        coupleName = self.GetCoupleName(playerID)
        coupleJob = self.GetCoupleJob(playerID)
        bridePriceMaxID = self.BridePriceMaxID
        return coupleID, coupleName, coupleJob, bridePriceMaxID
class DBPyCoupleManager(object):
    ## 伴侣数据管理
    def __init__(self):
        self.coupleDict = {} # {(playerIDA, playerIDB):PlayerCouple, ...}
        self.coupleIDDict = {} # {playerID:(playerIDA, playerIDB), ...} # 伴侣对应关系
        return
    def DelCouple(self, playerIDA, playerIDB):
        ## 删除伴侣数据,如果已离婚且均已通知,则可直接删除
        key = (playerIDA, playerIDB)
        if key in self.coupleDict:
            self.coupleDict.pop(key)
        if playerIDA in self.coupleIDDict and self.coupleIDDict[playerIDA] == key:
            self.coupleIDDict.pop(playerIDA)
        if playerIDB in self.coupleIDDict and self.coupleIDDict[playerIDB] == key:
            self.coupleIDDict.pop(playerIDB)
        return
    def AddCouple(self, playerIDA, playerIDB, coupleData):
        ## 添加新伴侣
        coupleKey = (playerIDA, playerIDB)
        couple = PlayerCouple(coupleData)
        self.coupleDict[coupleKey] = couple
        self.coupleIDDict[playerIDA] = coupleKey
        self.coupleIDDict[playerIDB] = coupleKey
        return couple
    def GetCouple(self, playerID):
        ## 获取伴侣
        coupleData = None
        # 不可能成立的条件,只是为了. 能出代码提示指向 PlayerCouple 类
        if False:
            coupleData = PlayerCouple(None)
        if playerID not in self.coupleIDDict:
            return coupleData
        coupleKey = self.coupleIDDict[playerID]
        if coupleKey not in self.coupleDict:
            return coupleData
        coupleData = self.coupleDict[coupleKey]
        return coupleData
    def SendMapServerCoupleInfo(self, syncPlayerIDList=None):
        ## 同步地图伴侣信息
        syncCoupleInfo = {}
        if syncPlayerIDList == None:
            syncPlayerIDList = self.coupleIDDict.keys()
        for playerID in syncPlayerIDList:
            couple = self.GetCouple(playerID)
            if not couple:
                syncCoupleInfo[playerID] = []
            else:
                syncCoupleInfo[playerID] = couple.GetSendMapServerCoupleInfo(playerID)
        GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CoupleInfo, syncCoupleInfo)
        return
    # 保存数据 存数据库和realtimebackup
    def GetSaveData(self):
        savaData = ""
        cntData = ""
        cnt = 0
        for couple in self.coupleDict.values():
            cnt += 1
            savaData += couple.coupleData.getBuffer()
        GameWorld.Log("Save DBPyMarry 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 DBPyMarry count :%s" % cnt)
        for _ in xrange(cnt):
            coupleData = PyGameDataStruct.tagDBPyCouple()
            coupleData.clear()
            pos += coupleData.readData(datas, pos, dataslen)
            playerIDA = coupleData.PlayerIDA
            playerIDB = coupleData.PlayerIDB
            couple = self.AddCouple(playerIDA, playerIDB, coupleData)
            if couple.GetBreakRequestTime() > 0:
                PyGameData.g_marryBreakInfo[(playerIDA, playerIDB)] = couple
        SortMarryBreak()
        return pos
class DBPyUnNotifyLoveGiftRecManager(object):
    ## 未通知的赠送礼物记录管理
    def __init__(self):
        self.unNotifyLoveGiftDict = {} # {playerID:[PyGameDataStruct.tagDBPyUnNotifyLoveGiftRec, ...], ...}
        return
    def AddUnNotifyGiftRec(self, receivePlayerID, givePlayerID, giftNum, giftCount, sendTime):
        ''' 添加未通知的赠送礼物记录
        @param receivePlayerID: 未通知的受赠方玩家ID
        @param givePlayerID: 赠送方玩家ID
        '''
        recData = PyGameDataStruct.tagDBPyUnNotifyLoveGiftRec()
        recData.PlayerID = receivePlayerID
        recData.GivePlayerID = givePlayerID
        recData.GiftNum = giftNum
        recData.GiftCount = giftCount
        recData.SendTime = sendTime
        if receivePlayerID not in self.unNotifyLoveGiftDict:
            self.unNotifyLoveGiftDict[receivePlayerID] = []
        giftList = self.unNotifyLoveGiftDict[receivePlayerID]
        giftList.append(recData)
        return
    def LoginNotify(self, curPlayer):
        receivePlayerID = curPlayer.GetPlayerID()
        if receivePlayerID not in self.unNotifyLoveGiftDict:
            return
        giftList = self.unNotifyLoveGiftDict.pop(receivePlayerID, [])
        sendGiftList = []
        for recData in giftList:
            giftOK = ChPyNetSendPack.tagGCSendGiftsOK()
            giftOK.PlayerID = recData.GivePlayerID
            giftOK.Name = PlayerSocial.GetSocialPlayerName(recData.GivePlayerID)
            giftOK.NameLen = len(giftOK.Name)
            giftOK.GiftNum = recData.GiftNum
            giftOK.GiftCount = recData.GiftCount
            giftOK.SendTime = recData.SendTime
            sendGiftList.append(giftOK)
        clientPack = ChPyNetSendPack.tagGCSendGiftsOKList()
        clientPack.SendGiftsOKList = sendGiftList
        clientPack.Count = len(clientPack.SendGiftsOKList)
        NetPackCommon.SendFakePack(curPlayer, clientPack)
        return
    # 保存数据 存数据库和realtimebackup
    def GetSaveData(self):
        savaData = ""
        cntData = ""
        cnt = 0
        for recDataList in self.unNotifyLoveGiftDict.values():
            for recData in recDataList:
                cnt += 1
                savaData += recData.getBuffer()
        GameWorld.Log("Save DBPyUnNotifyLoveGiftRec 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 DBPyUnNotifyLoveGiftRec count :%s" % cnt)
        for _ in xrange(cnt):
            recData = PyGameDataStruct.tagDBPyUnNotifyLoveGiftRec()
            recData.clear()
            pos += recData.readData(datas, pos, dataslen)
            playerID = recData.PlayerID
            if playerID not in self.unNotifyLoveGiftDict:
                self.unNotifyLoveGiftDict[playerID] = []
            recDataList = self.unNotifyLoveGiftDict[playerID]
            recDataList.append(recData)
        return pos
    
def AddProsperity(candyObj, addValue):
    candyObj.prosperity += addValue
@@ -100,11 +323,42 @@
    return
def DoOnDay():
    PlayerBillboard.ClearBillboardByIndex(ShareDefine.Def_BT_CharmDay)
    # 重置每日聘礼状态
    syncPlayerIDList = []
    coupleMgr = PyDataManager.GetDBPyCoupleManager()
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in range(ipyDataMgr.GetMarryCount()):
        ipyData = ipyDataMgr.GetMarryByIndex(index)
        if not ipyData.GetIsDayReset():
            continue
        bridePriceID = ipyData.GetBridePriceID()
        for couple in coupleMgr.coupleDict.values():
            bridePriceState = couple.GetBridePriceState()
            buyCount = couple.GetBridePriceBuyCount(bridePriceID)
            if not buyCount:
                continue
            coupleIDInfo = [couple.coupleData.PlayerIDA, couple.coupleData.PlayerIDB]
            updBridePriceState = couple.SetBridePriceBuyCount(bridePriceID, 0)
            GameWorld.DebugLog("重置每日聘礼次数: coupleIDInfo=%s,bridePriceState=%s,bridePriceID=%s,updBridePriceState=%s"
                               % (coupleIDInfo, bridePriceState, bridePriceID, updBridePriceState))
            syncPlayerIDList.extend(coupleIDInfo)
    if syncPlayerIDList:
        playerMgr = GameWorld.GetPlayerManager()
        syncPlayerIDList = list(set(syncPlayerIDList))
        for playerID in syncPlayerIDList:
            curPlayer = playerMgr.FindPlayerByID(playerID)
            if not curPlayer or PlayerControl.GetIsTJG(curPlayer):
                continue
            Sync_CoupleInfo(curPlayer)
    return
def OnPlayerLogin(curPlayer):
    __LoginCheckCouple(curPlayer)
    PyDataManager.GetDBPyUnNotifyLoveGiftRecManager().LoginNotify(curPlayer)
    Sync_CoupleInfo(curPlayer)
    Sync_CandyList(curPlayer)
    return
@@ -123,6 +377,22 @@
        PyGameData.g_marryCandyInfo.pop((candyObj.playerIDA, candyObj.playerIDB), None)
        
        __DoMarryCandyOver(candyObj)
    # 检查和离
    breakWaitTimes = IpyGameDataPY.GetFuncCfg("LoveMarryBreak", 5)
    doCount = len(PyGameData.g_marryBreakSortList)
    while doCount > 0 and PyGameData.g_marryBreakSortList:
        doCount -= 1
        couple = PyGameData.g_marryBreakSortList[0]
        if curTime <= (couple.GetBreakRequestTime() + breakWaitTimes):
            break
        playerIDA, playerIDB = couple.coupleData.PlayerIDA, couple.coupleData.PlayerIDB
        PyGameData.g_marryBreakSortList.pop(0)
        PyGameData.g_marryBreakInfo.pop((playerIDA, playerIDB), None)
        GameWorld.Log("和离提交请求到期,系统自动和离! playerIDA=%s,playerIDB=%s, len(g_marryBreakSortList)=%s"
                      % (playerIDA, playerIDB, len(PyGameData.g_marryBreakSortList)))
        __DoMarryBreakLogic(couple, 0)
        
    return
@@ -167,7 +437,6 @@
        return
    
    playerID = curPlayer.GetPlayerID()
    curTime = int(time.time())
    if reqPlayerID not in PyGameData.g_marryReqInfo:
        GameWorld.DebugLog("提亲请求不存在! reqPlayerID=%s" % reqPlayerID, playerID)
        PlayerControl.NotifyCode(curPlayer, "MarryReqInvalid")
@@ -180,21 +449,31 @@
        PlayerControl.NotifyCode(curPlayer, "MarryReqInvalid")
        return
    
    reqData = PyGameData.g_marryReqInfo.pop(reqPlayerID)
    bridePriceID = reqData.bridePriceID
    passSeconds = curTime - reqData.reqTime
    reqSecondCD = IpyGameDataPY.GetFuncCfg("LoveMarry", 1)
    if passSeconds > reqSecondCD:
    if __CheckMarryReqTimeout(reqData):
        GameWorld.DebugLog("提亲请求已超时! reqPlayerID=%s" % reqPlayerID, playerID)
        PlayerControl.NotifyCode(curPlayer, "MarryReqInvalid")
        PyGameData.g_marryReqInfo.pop(reqPlayerID, None)
        return
    
    __DoMarryResponse(curPlayer, reqPlayer, reqPlayerID, isOK)
    return
def __DoMarryResponse(curPlayer, reqPlayer, reqPlayerID, isOK):
    ''' 提亲回应
    @param curPlayer: 回应玩家
    @param reqPlayer: 提亲玩家
    @param isOK: 是否统一
    '''
    reqData = PyGameData.g_marryReqInfo.pop(reqPlayerID, None)
    if not reqData:
        return
    bridePriceID = reqData.bridePriceID
    ipyData = IpyGameDataPY.GetIpyGameData("Marry", bridePriceID)
    if not ipyData:
        return
    
    reqPlayerName = reqPlayer.GetName()
    playerID = curPlayer.GetPlayerID()
    reqPlayerName = reqPlayer.GetName() if reqPlayer else PlayerSocial.GetSocialPlayerName(reqPlayerID)
    playerName = curPlayer.GetName()
    
    responsePack = ChPyNetSendPack.tagGCMarryResponseRet()
@@ -205,6 +484,7 @@
    responsePack.PlayerNameB = playerName
    responsePack.NameBLen = len(responsePack.PlayerNameB)
    responsePack.IsOK = isOK
    if reqPlayer:
    NetPackCommon.SendFakePack(reqPlayer, responsePack) # 必回复提亲方
    # 拒绝
    if not isOK:
@@ -212,6 +492,9 @@
    NetPackCommon.SendFakePack(curPlayer, responsePack) # 回应方仅同意时同步
    
    # ===================== 以下执行成亲逻辑 ===================== 
    GameWorld.Log("执行成亲: reqPlayerID=%s,playerID=%s,bridePriceID=%s" % (reqPlayerID, playerID, bridePriceID), playerID)
    curTime = int(time.time())
    prosperity = ipyData.GetProsperity()
    candyTimes = ipyData.GetCandyTimes()
    brideGiftItemInfo = ipyData.GetBrideGiftItemInfo()
@@ -222,26 +505,49 @@
            paramList.extend([itemID, itemCount])
        PlayerControl.WorldNotify(0, worldNotifyKey, paramList)
        
    for player, coupleID, coupleName in [[reqPlayer, playerID, playerName], [curPlayer, reqPlayerID, reqPlayerName]]:
        PlayerControl.SetCoupleID(player, coupleID)
    coupleMgr = PyDataManager.GetDBPyCoupleManager()
    couple = coupleMgr.GetCouple(playerID)
    if not couple:
        GameWorld.Log("    新婚: reqPlayerID=%s,playerID=%s,bridePriceID=%s" % (reqPlayerID, playerID, bridePriceID), playerID)
        coupleData = PyGameDataStruct.tagDBPyCouple()
        coupleData.PlayerIDA = reqPlayerID
        coupleData.PlayerNameA = reqPlayerName
        coupleData.PlayerIDB = playerID
        coupleData.PlayerNameB = playerName
        coupleData.NewMarryTime = curTime
        couple = coupleMgr.AddCouple(reqPlayerID, playerID, coupleData)
        
        # 更新社交关系
        socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(player.GetPlayerID())
        if socialPlayer:
            socialPlayer.SetCoupleInfo(coupleID, coupleName)
            socialPlayer.CheckUpdCouplePriceMaxID(bridePriceID)
        # 通知给相关社交人员
        PlayerSocial.NotifySocialCoupleChange(reqPlayerID, playerID)
        PlayerSocial.NotifySocialCoupleChange(playerID, reqPlayerID)
            
        # 通知地图玩家
        dataMsg = [reqPlayerID, coupleID, curTime, bridePriceID]
        # 通知地图全局伴侣信息
        PyDataManager.GetDBPyCoupleManager().SendMapServerCoupleInfo([playerID, reqPlayerID])
    else:
        GameWorld.Log("    已婚,再次提亲: PlayerIDA=%s,PlayerIDB=%s, cur reqPlayerID=%s,playerID=%s,bridePriceID=%s"
                      % (couple.coupleData.PlayerIDA, couple.coupleData.PlayerIDB, reqPlayerID, playerID, bridePriceID), playerID)
    couple.coupleData.MarryTime = curTime
    updBuyCountValue = couple.SetBridePriceBuyCount(bridePriceID, couple.GetBridePriceBuyCount(bridePriceID) + 1)
    GameWorld.Log("    updBuyCountValue=%s" % updBuyCountValue, playerID)
    if bridePriceID > couple.BridePriceMaxID:
        couple.BridePriceMaxID = bridePriceID
        GameWorld.Log("    update BridePriceMaxID=%s" % couple.BridePriceMaxID, playerID)
    # 通知玩家
    for player in [reqPlayer, curPlayer]:
        if not player:
            continue
        mapServerCoupleInfo = couple.GetSendMapServerCoupleInfo(player.GetPlayerID())
        dataMsg = [reqPlayerID, bridePriceID, mapServerCoupleInfo]
        MapServer_QueryPlayer_DoLogic_Love(player, "MarrySuccess", dataMsg, playerID)
        Sync_CoupleInfo(player)
        
    # 聘礼奖励发邮件
    playerIDList = [reqPlayerID, playerID]
    paramList = [reqPlayerName, playerName]
    PlayerCompensation.SendMailByKey("MarrySuccess", playerIDList, brideGiftItemInfo, paramList)
    # 通知地图全局伴侣信息
    PlayerSocial.SendMapServerCoupleInfo([playerID, reqPlayerID])
    
    # 新增喜糖
    candyObj = MarryCandy()
@@ -255,11 +561,27 @@
    AddProsperity(candyObj, prosperity)
    
    PyGameData.g_marryCandyInfo[(reqPlayerID, playerID)] = candyObj
    __SortCandy()
    Sync_CandyList(None, [candyObj])
    return True
def __SortCandy():
    PyGameData.g_marryCandySortList = PyGameData.g_marryCandyInfo.values()
    PyGameData.g_marryCandySortList.sort(key=operator.attrgetter("endTime"))
    Sync_CandyList(None, [candyObj])
    return
def SortMarryBreak():
    PyGameData.g_marryBreakSortList = PyGameData.g_marryBreakInfo.values()
    PyGameData.g_marryBreakSortList.sort(key=operator.attrgetter("coupleData.BreakRequestTime"))
    #GameWorld.DebugLog("SortMarryBreak count=%s" % len(PyGameData.g_marryBreakSortList))
    return
def __CheckMarryReqTimeout(reqData):
    ## 检查提亲是否超时
    curTime = int(time.time())
    passSeconds = curTime - reqData.reqTime
    reqSecondCD = IpyGameDataPY.GetFuncCfg("LoveMarry", 1)
    return passSeconds > reqSecondCD
#// B3 16 和平离婚回应 #tagGCMarryBreakResponse
#
@@ -273,103 +595,89 @@
    isOK = clientData.IsOK
    
    playerID = curPlayer.GetPlayerID()
    coupleID = PlayerControl.GetCoupleID(curPlayer)
    if not coupleID:
    couple = PyDataManager.GetDBPyCoupleManager().GetCouple(playerID)
    if not couple:
        GameWorld.Log("没有伴侣,无法回应和离! ", playerID)
        return
    coupleID = couple.GetCoupleID(playerID)
    breakRequestID = couple.GetBreakRequestID()
    if not breakRequestID or coupleID != breakRequestID:
        GameWorld.Log("伴侣没有提出和离,无法回应和离! coupleID=%s,breakRequestID=%s"
                      % (coupleID, breakRequestID), playerID)
        return
    
    if coupleID not in PyGameData.g_marryBreakReqInfo:
        GameWorld.DebugLog("对方没有请求和离,回应无效! coupleID=%s" % coupleID, playerID)
        return
    if playerID != PyGameData.g_marryBreakReqInfo[coupleID]:
        GameWorld.DebugLog("非对方没有请求和离对象,回应无效! reqPlayerID=%s,tagPlayerID=%s"
                           % (coupleID, PyGameData.g_marryBreakReqInfo[coupleID]), playerID)
        return
    PyGameData.g_marryBreakReqInfo.pop(coupleID, None)
    playerIDA, playerIDB = couple.coupleData.PlayerIDA, couple.coupleData.PlayerIDB
    if (playerIDA, playerIDB) in PyGameData.g_marryBreakInfo:
        PyGameData.g_marryBreakInfo.pop((playerIDA, playerIDB), None)
        SortMarryBreak()
    
    if not isOK:
        GameWorld.Log("拒绝和离! coupleID=%s" % coupleID, playerID)
        couple.SetBreakRequestID(0) # 清除和离请求ID
        Sync_CoupleInfo(curPlayer)
        tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(coupleID)
        if tagPlayer and not PlayerControl.GetIsTJG(tagPlayer):
            Sync_CoupleInfo(tagPlayer)
        PlayerCompensation.SendMailByKey("MarryBreakRefuse", [coupleID], [], [curPlayer.GetName()])
        return
    
    GameWorld.Log("同意和离: coupleID=%s" % coupleID, playerID)
    
    __DoMarryBreak(curPlayer, coupleID)
    __DoMarryBreakLogic(couple, playerID)
    return
def __DoMarryBreak(curPlayer, coupleID):
def __DoMarryBreakLogic(couple, playerID=0):
    ## 执行离婚 
    
    playerID = curPlayer.GetPlayerID()
    __ClearCoupleSocial(curPlayer)
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(coupleID)
    if tagPlayer:
        __ClearCoupleSocial(tagPlayer)
    # 未在线,标记离婚状态,等下次玩家上线处理
    else:
        socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(coupleID)
        if socialPlayer:
            socialPlayer.SetCoupleBreakOffline()
            GameWorld.Log("离婚时伴侣不在线,标记伴侣社交关系已离婚!等下次上线处理! coupleID=%s" % coupleID, playerID)
    # 通知地图全局伴侣信息
    PlayerSocial.SendMapServerCoupleInfo([playerID, coupleID])
    if not couple:
    return
def __LoginCheckCouple(curPlayer):
    ## 登录检查是否已被离婚
    playerID = curPlayer.GetPlayerID()
    coupleID = PlayerControl.GetCoupleID(curPlayer)
    if not coupleID:
        return
    playerIDA = couple.coupleData.PlayerIDA
    playerIDB = couple.coupleData.PlayerIDB
    
    socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(playerID)
    if socialPlayer == None or socialPlayer.GetCoupleBreakOffline():
        GameWorld.Log("玩家上线检测到已被离婚,执行解除伴侣关系!coupleID=%s" % coupleID, playerID)
        __ClearCoupleSocial(curPlayer)
    coupleMgr = PyDataManager.GetDBPyCoupleManager()
        
    # 上线未同步过地图全局伴侣信息的则同步
    if socialPlayer and not socialPlayer.syncMapCouple and socialPlayer.GetCoupleID():
        PlayerSocial.SendMapServerCoupleInfo([playerID])
    return
def __ClearCoupleSocial(curPlayer):
    ## 清除伴侣社交关系
    coupleID = PlayerControl.GetCoupleID(curPlayer)
    coupleName = ""
    playerID = curPlayer.GetPlayerID()
    GameWorld.Log("玩家执行解除伴侣关系! coupleID=%s" % coupleID, playerID)
    if coupleID:
        # 亲密度减少
        curFriends = PyDataManager.GetFriendManager().GetFriends(playerID)
        if curFriends != None:
            decIntimacyPer = IpyGameDataPY.GetFuncCfg("LoveMarryBreak", 3)
            updIntimacy = curFriends.AddIntimacyByPer(curPlayer, coupleID, -decIntimacyPer)
            GameWorld.Log("    更新自身与对方亲密度: tagPlayerID=%s,decIntimacyPer=%s,updIntimacy=%s" % (coupleID, decIntimacyPer, updIntimacy), playerID)
    # 通知地图
    dataMsg = []
    MapServer_QueryPlayer_DoLogic_Love(curPlayer, "ClearCoupleSocial", dataMsg, playerID)
    # 清社交关系 - 由地图清除后同步更新
    PlayerControl.SetCoupleID(curPlayer, 0)
    socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(playerID)
    if socialPlayer:
        coupleName = socialPlayer.playerInfo.CoupleName
        socialPlayer.SetCoupleInfo(0, "")
        socialPlayer.CheckUpdCouplePriceMaxID(0)
    decIntimacyPer = IpyGameDataPY.GetFuncCfg("LoveMarryBreak", 4)
    if decIntimacyPer:
        PyDataManager.GetIntimacyManager().DelIntimacyBothPer(playerIDA, playerIDB, decIntimacyPer)
        
    # 邮件通知离婚
    playerIDList = [playerID]
    for pid in [playerIDA, playerIDB]:
        coupleName = couple.GetCoupleName(pid)
        playerIDList = [pid]
    paramList = [coupleName]
    PlayerCompensation.SendMailByKey("MarryBreakOK", playerIDList, [], paramList)
    return
    coupleMgr.DelCouple(playerIDA, playerIDB)
    # 通知地图全局伴侣信息
    PyDataManager.GetDBPyCoupleManager().SendMapServerCoupleInfo([playerIDA, playerIDB])
    # 通知玩家
    dataMsg = []
    for pid in [playerIDA, playerIDB]:
        tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(pid)
        if tagPlayer and not PlayerControl.GetIsTJG(tagPlayer):
            MapServer_QueryPlayer_DoLogic_Love(tagPlayer, "ClearCoupleSocial", dataMsg, playerID)
            Sync_CoupleInfo(tagPlayer)
    # 通知给相关社交人员
    PlayerSocial.NotifySocialCoupleChange(playerIDA, 0)
    PlayerSocial.NotifySocialCoupleChange(playerIDB, 0)
    if (playerIDA, playerIDB) in PyGameData.g_marryCandyInfo:
        GameWorld.Log("离婚时同步清除喜糖宴会: playerIDA=%s, playerIDB=%s" % (playerIDA, playerIDB), playerID)
        PyGameData.g_marryCandyInfo.pop((playerIDA, playerIDB))
        __SortCandy()
        Sync_CandyList(None)
    if (playerIDA, playerIDB) in PyGameData.g_marryBreakInfo:
        GameWorld.Log("离婚时同步清除和离请求: playerIDA=%s, playerIDB=%s" % (playerIDA, playerIDB), playerID)
        PyGameData.g_marryBreakInfo.pop((playerIDA, playerIDB), None)
        SortMarryBreak()
    return True
def MapServer_Love(curPlayer, msgList):
    mapID = curPlayer.GetRealMapID()
@@ -379,13 +687,13 @@
    
    msgType, dataMsg = msgList
    
    # 送花请求
    if msgType == "SendFlowersReq":
        ret = __CheckSendFlowers(curPlayer, dataMsg)
    # 送礼物请求
    if msgType == "SendGiftsReq":
        ret = __SendGiftsReq(curPlayer, dataMsg)
        
    # 送花OK
    elif msgType == "SendFlowersOK":
        __DoSendFlowersOK(curPlayer, dataMsg)
    # 送礼物
    elif msgType == "SendGiftsOK":
        __DoSendGiftsOK(curPlayer, dataMsg)
        return
    
    # 提亲
@@ -409,63 +717,70 @@
        return
    return msgList + [ret]
def __CheckSendFlowers(curPlayer, dataMsg):
    ## 在线好友可赠送
def __SendGiftsReq(curPlayer, dataMsg):
    ## 送礼物请求
    tagPlayerID = dataMsg[0]
    playerID = curPlayer.GetPlayerID()
    curFriends = PyDataManager.GetFriendManager().GetFriends(playerID)
    if curFriends == None:
        return
    curFriend = curFriends.Find(tagPlayerID)
    if curFriend == None:
        PlayerControl.NotifyCode(curPlayer, "NotFriend")
        return
    
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
    if not tagPlayer or PlayerControl.GetIsTJG(tagPlayer):
        PlayerControl.NotifyCode(curPlayer, "LoveOffline")
    # 黑名单检查
    if PyDataManager.GetBlacklistManager().CheckBlacklistBoth(playerID, tagPlayerID, curPlayer):
        return
    
    return True
def __DoSendFlowersOK(curPlayer, dataMsg):
    ## 送花OK
def __DoSendGiftsOK(curPlayer, dataMsg):
    ## 送礼物
    
    playerID = curPlayer.GetPlayerID()
    playerName = curPlayer.GetName()
    
    tagPlayerID, flowerID, flowerCount, addCharm, addCharmTag, addIntimacy, isWorldNotify = dataMsg
    tagPlayerID, giftNum, giftItemID, giftCount, isAutoBuy = dataMsg
    
    GameWorld.Log("赠送鲜花OK: tagPlayerID=%s,flowerCount=%s,addCharm=%s,addCharmTag=%s,addIntimacy=%s"
                  % (tagPlayerID, flowerCount, addCharm, addCharmTag, addIntimacy), playerID)
    ipyData = IpyGameDataPY.GetIpyGameData("LoveGift", giftNum)
    if not ipyData:
        return
        
    curFriends = PyDataManager.GetFriendManager().GetFriends(playerID)
    if curFriends != None:
        updIntimacy = curFriends.AddIntimacy(curPlayer, tagPlayerID, addIntimacy)
        GameWorld.Log("    增加自身与对方亲密度: tagPlayerID=%s,updIntimacy=%s" % (tagPlayerID, updIntimacy), playerID)
    addCharmSelf = ipyData.GetAddCharmSelf() * giftCount
    addCharmTag = ipyData.GetAddCharmTag() * giftCount
    addIntimacy = ipyData.GetAddIntimacy() * giftCount
    worldNotifyKey = ipyData.GetWorldNotifyKey()
    GameWorld.Log("赠送礼物: tagPlayerID=%s,giftNum=%s,giftItemID=%s,giftCount=%s,addCharmSelf=%s,addCharmTag=%s,addIntimacy=%s,isAutoBuy=%s"
                  % (tagPlayerID, giftNum, giftItemID, giftCount, addCharmSelf, addCharmTag, addIntimacy, isAutoBuy), playerID)
        
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
    if not tagPlayer or PlayerControl.GetIsTJG(tagPlayer):
        return
    PyDataManager.GetIntimacyManager().AddIntimacyBoth(playerID, tagPlayerID, addIntimacy)
    PlayerCharm.AddCharm(curPlayer, playerID, playerID, addCharmSelf)
    PlayerCharm.AddCharm(tagPlayer, tagPlayerID, playerID, addCharmTag)
    tagPlayerName = ""
    isOnline = tagPlayer and not PlayerControl.GetIsTJG(tagPlayer)
    if isOnline:
    tagPlayerName = tagPlayer.GetName()
    else:
        tagPlayerName = PlayerSocial.GetSocialPlayerName(tagPlayerID)
    
    tagFriends = PyDataManager.GetFriendManager().GetFriends(tagPlayerID)
    if tagFriends != None:
        updIntimacy = tagFriends.AddIntimacy(tagPlayer, playerID, addIntimacy)
        GameWorld.Log("    增加对方与自身亲密度: tagPlayerID=%s,updIntimacy=%s" % (tagPlayerID, updIntimacy), playerID)
    if worldNotifyKey:
        PlayerControl.WorldNotify(0, worldNotifyKey, [playerName, tagPlayerName, giftItemID, giftCount])
        
    if isWorldNotify:
        PlayerControl.WorldNotify(0, "SendFlowers%s" % flowerCount, [playerName, tagPlayerName, flowerCount, flowerID])
    dataMsg = [addCharmTag]
    MapServer_QueryPlayer_DoLogic_Love(tagPlayer, "AddCharm", dataMsg, playerID)
    sendTime = int(time.time())
    if not isOnline:
        PyDataManager.GetDBPyUnNotifyLoveGiftRecManager().AddUnNotifyGiftRec(tagPlayerID, playerID, giftNum, giftCount, sendTime)
        return
        
    # 通知目标前端送花成功
    clientPack = ChPyNetSendPack.tagGCSendFlowersOK()
    clientPack.PlayerID = playerID
    clientPack.Name = playerName
    clientPack.NameLen = len(clientPack.Name)
    clientPack.FlowerCount = flowerCount
    giftOK = ChPyNetSendPack.tagGCSendGiftsOK()
    giftOK.PlayerID = playerID
    giftOK.Name = playerName
    giftOK.NameLen = len(giftOK.Name)
    giftOK.GiftNum = giftNum
    giftOK.GiftCount = giftCount
    giftOK.SendTime = sendTime
    clientPack = ChPyNetSendPack.tagGCSendGiftsOKList()
    clientPack.SendGiftsOKList = [giftOK]
    clientPack.Count = len(clientPack.SendGiftsOKList)
    NetPackCommon.SendFakePack(tagPlayer, clientPack)
    return
@@ -485,33 +800,30 @@
    ## 成亲通用检查
    
    playerID = curPlayer.GetPlayerID()
    curFriends = PyDataManager.GetFriendManager().GetFriends(playerID)
    if curFriends == None:
        PlayerControl.NotifyCode(curPlayer, "NotFriend") # 非好友
        return
    curFriend = curFriends.Find(tagPlayerID)
    if curFriend == None:
        PlayerControl.NotifyCode(curPlayer, "NotFriend") # 非好友
    # 黑名单检查
    if PyDataManager.GetBlacklistManager().CheckBlacklistBoth(playerID, tagPlayerID, curPlayer):
        return
    
    if not tagPlayer or PlayerControl.GetIsTJG(tagPlayer):
        PlayerControl.NotifyCode(curPlayer, "LoveOffline") # 离线
        return
    
    coupleID = PlayerControl.GetCoupleID(curPlayer)
    if coupleID and coupleID != tagPlayerID:
        PlayerControl.NotifyCode(curPlayer, "TagHaveCouple") # 已经有其他伴侣了
    curCouple = PyDataManager.GetDBPyCoupleManager().GetCouple(playerID)
    if curCouple and curCouple.GetCoupleID(playerID) != tagPlayerID:
        PlayerControl.NotifyCode(curPlayer, "HaveCouple") # 已经有其他伴侣了
        return
    
    tagCoupleID = PlayerControl.GetCoupleID(tagPlayer)
    if tagCoupleID and tagCoupleID != playerID:
        PlayerControl.NotifyCode(curPlayer, "TagHaveCouple") # 已经有其他伴侣了
    tagCouple = PyDataManager.GetDBPyCoupleManager().GetCouple(tagPlayerID)
    if tagCouple and tagCouple.GetCoupleID(tagPlayerID) != playerID:
        PlayerControl.NotifyCode(curPlayer, "TagHaveCouple") # 对方已经有其他伴侣了
        return
    
    # 回应方可不检查亲密度
    if checkIntimacy:
        needIntimacy = IpyGameDataPY.GetFuncCfg("LoveMarry", 2)
        if curFriend.Intimacy < needIntimacy:
        curIntimacys = PyDataManager.GetIntimacyManager().GetIntimacys(playerID)
        if not curIntimacys or curIntimacys.GetTagIntimacy(tagPlayerID) < needIntimacy:
            PlayerControl.NotifyCode(curPlayer, "IntimacyLack", [needIntimacy]) # 亲密度不足
            return
        
@@ -532,6 +844,34 @@
    if (playerID, tagPlayerID) in PyGameData.g_marryCandyInfo or (tagPlayerID, playerID) in PyGameData.g_marryCandyInfo:
        PlayerControl.NotifyCode(curPlayer, "MarryReqLimitByCandy") # 喜宴中无法操作
        return
    couple = PyDataManager.GetDBPyCoupleManager().GetCouple(playerID)
    if couple:
        coupleID = couple.GetCoupleID(playerID)
        if coupleID != tagPlayerID:
            GameWorld.Log("已成亲伴侣ID不一致,无法提亲! tagPlayerID(%s) != coupleID(%s)" % (tagPlayerID, coupleID), playerID)
            return
        ipyData = IpyGameDataPY.GetIpyGameData("Marry", bridePriceID)
        if not ipyData:
            return
        canBuyMax = ipyData.GetCanBuyCount()
        buyCount = couple.GetBridePriceBuyCount(bridePriceID)
        GameWorld.DebugLog("bridePriceID=%s,buyCount=%s,canBuyMax=%s %s" % (bridePriceID, buyCount, canBuyMax, couple.coupleData.BridePriceState))
        if canBuyMax and buyCount >= canBuyMax:
            GameWorld.Log("聘礼提亲次数不足,无法提亲! bridePriceID=%s,buyCount(%s) >= canBuyMax(%s)"
                          % (bridePriceID, buyCount, canBuyMax), playerID)
            return
    if tagPlayerID in PyGameData.g_marryReqInfo:
        tagReqData = PyGameData.g_marryReqInfo[tagPlayerID]
        if playerID == tagReqData.playerIDB and not __CheckMarryReqTimeout(tagReqData):
            GameWorld.Log("玩家提亲时,目标刚好已经先提过亲,且在有效期内,直接成亲!tagPlayerID=%s" % tagPlayerID, playerID)
            if __DoMarryResponse(curPlayer, tagPlayer, tagPlayerID, 1):
                return
        else:
            GameWorld.DebugLog("对方有提亲,但是对象不一样或已超时! tagPlayerID=%s, timeout=%s" % (tagReqData.playerIDB, __CheckMarryReqTimeout(tagReqData)), playerID)
    
    curTime = int(time.time())
    if playerID not in PyGameData.g_marryReqInfo:
@@ -631,44 +971,82 @@
def __DoMarryBreakReq(curPlayer, dataMsg):
    ## 离婚请求
    playerID, coupleID, breakType, moneyType, moneyValue = dataMsg
    playerID, breakType, moneyType, moneyValue = dataMsg
    
    gameServerCoupleID = PlayerControl.GetCoupleID(curPlayer)
    socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(playerID)
    socialCoupleID = 0 if not socialPlayer else socialPlayer.GetCoupleID()
    couple = PyDataManager.GetDBPyCoupleManager().GetCouple(playerID)
    if not couple:
        GameWorld.Log("没有伴侣,不需要离婚! ", playerID)
        return
    coupleID = couple.GetCoupleID(playerID)
    
    if not gameServerCoupleID or coupleID != gameServerCoupleID or not socialCoupleID or coupleID != socialCoupleID:
        GameWorld.ErrLog("地图玩家伴侣数据与GameServer不一致,离婚请求时直接通过! gameServerCoupleID=%s,socialCoupleID=%s,mapCoupleID=%s"
                         % (gameServerCoupleID, socialCoupleID, coupleID), playerID)
        __ClearCoupleSocial(curPlayer)
        PlayerSocial.SendMapServerCoupleInfo([playerID])
    curTime = int(time.time())
    # 公共CD
    marryTime = couple.GetMarryTime()
    passTime = curTime - marryTime
    marryBreakCD = IpyGameDataPY.GetFuncCfg("LoveMarryBreak", 1)
    if marryBreakCD and passTime < marryBreakCD:
        GameWorld.Log("距离最近一次成亲离婚等待时间未到,无法请求离婚! marryTime=%s,passTime(%s) < %s"
                      % (GameWorld.ChangeTimeNumToStr(marryTime), passTime, marryBreakCD), playerID)
        return
    
    if (playerID, coupleID) in PyGameData.g_marryCandyInfo or (coupleID, playerID) in PyGameData.g_marryCandyInfo:
        PlayerControl.NotifyCode(curPlayer, "MarryReqLimitByCandy") # 喜宴中无法操作
    # 和离额外限制个人CD
    playerBreakRequestTime = couple.GetPlayerBreakRequestTime(playerID)
    if breakType == 0 and playerBreakRequestTime:
        passTime = curTime - playerBreakRequestTime
        breakReqCD = IpyGameDataPY.GetFuncCfg("LoveMarryBreak", 2)
        if breakReqCD and passTime < breakReqCD:
            GameWorld.Log("距离最近一次请求和离等待时间未到,无法请求离婚! playerBreakRequestTime=%s,passTime(%s) < %s"
                          % (GameWorld.ChangeTimeNumToStr(playerBreakRequestTime), passTime, breakReqCD), playerID)
            return
    if couple.GetBreakRequestID() == coupleID:
        GameWorld.Log("请求离婚时对方已经提出和离了,直接离婚! coupleID=%s,breakRequestID=%s"
                      % (coupleID, couple.GetBreakRequestID()), playerID)
        __DoMarryBreakLogic(couple, playerID)
        return
    
    # 0-和平离婚;1-强制离婚
    if breakType == 0:
        if couple.GetBreakRequestID() != playerID:
            playerIDA, playerIDB = couple.coupleData.PlayerIDA, couple.coupleData.PlayerIDB
            GameWorld.Log("新增提交和离! coupleID=%s" % coupleID, playerID)
            couple.SetBreakRequestID(playerID)
            PyGameData.g_marryBreakInfo[(playerIDA, playerIDB)] = couple
            SortMarryBreak()
            playerBreakRequestTime = couple.GetPlayerBreakRequestTime(playerID)
        else:
            GameWorld.Log("重复提交和离! coupleID=%s" % coupleID, playerID)
        Sync_CoupleInfo(curPlayer)
        tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(coupleID)
        if not tagPlayer or PlayerControl.GetIsTJG(tagPlayer):
            PlayerControl.NotifyCode(curPlayer, "LoveOffline") # 离线
            return
        clientPack = ChPyNetSendPack.tagGCMarryBreakInfo()
        clientPack.PlayerID = playerID
        clientPack.PlayerName = curPlayer.GetName()
        clientPack.NameLen = len(clientPack.PlayerName)
        NetPackCommon.SendFakePack(tagPlayer, clientPack)
        PyGameData.g_marryBreakReqInfo[playerID] = coupleID
        if tagPlayer and not PlayerControl.GetIsTJG(tagPlayer):
            Sync_CoupleInfo(tagPlayer)
        return
    
    GameWorld.Log("强制离婚: coupleID=%s" % coupleID, playerID)
    __DoMarryBreak(curPlayer, coupleID)
    __DoMarryBreakLogic(couple, playerID)
    
    return moneyType, moneyValue
def Sync_CoupleInfo(curPlayer):
    ## 同步伴侣信息
    playerID = curPlayer.GetPlayerID()
    clientPack = ChPyNetSendPack.tagGCCoupleInfo()
    curCouple = PyDataManager.GetDBPyCoupleManager().GetCouple(playerID)
    if curCouple:
        clientPack.CoupleID = curCouple.GetCoupleID(playerID)
        clientPack.CoupleName = curCouple.GetCoupleName(playerID)
        clientPack.NameLen = len(clientPack.CoupleName)
        clientPack.NewMarryTime = curCouple.GetNewMarryTime()
        clientPack.MarryTime = curCouple.GetMarryTime()
        clientPack.BridePriceState = curCouple.GetBridePriceState()
        clientPack.BreakRequestID = curCouple.GetBreakRequestID()
        clientPack.BreakRequestTime = curCouple.GetBreakRequestTime()
        clientPack.PlayerBreakRequestTime = curCouple.GetPlayerBreakRequestTime(playerID)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
def Sync_CandyList(curPlayer, syncCandyList=None):
    if syncCandyList == None:
        syncCandyList = PyGameData.g_marryCandySortList