hxp
2021-11-17 ffa8a645ed6a92a3c723bbf5c7f1eb4d5425c826
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py
@@ -139,8 +139,10 @@
            inPack = ChPyNetSendPack.tagGCGroupPlayer()
            inPack.PlayerID = player.TagID
            
            inPack.SortValue = player.Timestamp if hasattr(player, 'Timestamp') else 0
            inPack.Intimacy = player.Intimacy if hasattr(player, 'Intimacy') else 0
            if hasattr(player, 'Intimacy'):
                inPack.SortValue = player.Intimacy
            else:
                inPack.SortValue = player.Timestamp if hasattr(player, 'Timestamp') else 0
            pack.Players.append(inPack)
            
        pack.Count = len(pack.Players)
@@ -196,48 +198,7 @@
        self.Delete(delFriendID)
        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(self.PlayerID)
        self.MapServer_SyncFriendInfo(curPlayer)
    def AddIntimacy(self, curPlayer, friendID, addValue):
        ## 增加亲密度 - 支持正负
        if friendID not in self.SocialDict:
            return 0
        friendObj = self.SocialDict[friendID]
        friendObj.Intimacy += addValue
        friendObj.Intimacy = max(0, min(friendObj.Intimacy, ShareDefine.Def_UpperLimit_DWord))
        
        if not curPlayer:
            return friendObj.Intimacy
        friendName = ""
        socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(friendID)
        if socialPlayer:
            friendName = socialPlayer.playerInfo.PlayerName
        if addValue > 0:
            PlayerControl.NotifyCode(curPlayer, "AddIntimacy", [friendName, addValue])
        self.Sync_SocialsInfo(curPlayer, [friendID])
        return friendObj.Intimacy
    def AddIntimacyByPer(self, curPlayer, friendID, addPer):
        ## 增加亲密度 - 根据百分比,支持正负
        if friendID not in self.SocialDict:
            return 0
        friendObj = self.SocialDict[friendID]
        addValue = int(friendObj.Intimacy * addPer / 100.0)
        return self.AddIntimacy(curPlayer, friendID, addValue)
    def SetIntimacy(self, curPlayer, friendID, setValue):
        ## 直接设置亲密度 - 一般GM测试使用
        if friendID not in self.SocialDict:
            return
        friendObj = self.SocialDict[friendID]
        friendObj.Intimacy = setValue
        if curPlayer:
            self.Sync_SocialsInfo(curPlayer, [friendID])
        return friendObj.Intimacy
    # 通知地图好友信息
    def MapServer_SyncFriendInfo(self, curPlayer):
        return
@@ -334,6 +295,144 @@
            self.PlayerFriends[playerFriend.PlayerID].SocialDict[playerFriend.TagID] = playerFriend
            
            AddBeSocial(playerFriend.TagID, playerFriend.PlayerID)
        return pos
#-------------------亲密------------------------------
# 某个玩家的亲密组管理
class Intimacys(SocialPlayers):
    def __init__(self, PlayerID):
        super(Intimacys, self).__init__(PlayerID, PyGameDataStruct.tagDBPyPlayerIntimacy,
                                        ChConfig.Def_SocialGroup_Intimacy)
    def GetIntimacyObj(self, tagID):
        if tagID not in self.SocialDict:
            self.Add(tagID)
        return self.SocialDict.get(tagID)
    def GetTagIntimacy(self, tagID):
        intimacyObj = self.Find(tagID)
        return intimacyObj.Intimacy if intimacyObj else 0
    def AddIntimacy(self, curPlayer, tagID, addValue):
        ## 增加亲密度 - 支持正负、支持离线, curPlayer 可能为None
        intimacyObj = self.GetIntimacyObj(tagID)
        if not intimacyObj:
            return 0
        if not intimacyObj.Intimacy and addValue < 0:
            return 0
        intimacyObj.Intimacy = min(max(0, intimacyObj.Intimacy + addValue), ShareDefine.Def_UpperLimit_DWord)
        nowIntimacy = intimacyObj.Intimacy
        if nowIntimacy <= 0:
            self.Delete(tagID)
        if not curPlayer:
            return nowIntimacy
        tagName = ""
        socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(tagID)
        if socialPlayer:
            tagName = socialPlayer.playerInfo.PlayerName
        if addValue > 0:
            PlayerControl.NotifyCode(curPlayer, "AddIntimacy", [tagName, addValue])
        elif addValue < 0:
            PlayerControl.NotifyCode(curPlayer, "DelIntimacy", [tagName, abs(addValue)])
        self.Sync_SocialsInfo(curPlayer, [tagID])
        return nowIntimacy
    def SetIntimacy(self, curPlayer, tagID, setValue):
        ## 直接设置亲密度 - 一般GM测试使用
        intimacyObj = self.GetIntimacyObj(tagID)
        if not intimacyObj:
            return 0
        intimacyObj.Intimacy = setValue
        if curPlayer:
            self.Sync_SocialsInfo(curPlayer, [tagID])
        return intimacyObj.Intimacy
# 整个游戏的亲密管理
class IntimacyManager(object):
    def __init__(self):
        self.PlayerIntimacys = {}     # PyGameDataStruct.tagDBPyPlayerIntimacy
        return
    # 增加双方亲密度
    def AddIntimacyBoth(self, aID, bID, addValue):
        for playerID, tagPlayerID in {aID:bID, bID:aID}.items():
            intimacys = self.GetIntimacys(playerID)
            if not intimacys:
                continue
            intimacyObj = intimacys.GetIntimacyObj(tagPlayerID)
            if not intimacyObj:
                continue
            curIntimacy = intimacyObj.Intimacy
            curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
            updIntimacy = intimacys.AddIntimacy(curPlayer, tagPlayerID, addValue)
            GameWorld.DebugLog("增加亲密度: playerID=%s,tagPlayerID=%s,curIntimacy=%s,addValue=%s,updIntimacy=%s"
                               % (playerID, tagPlayerID, curIntimacy, addValue, updIntimacy), playerID)
        return
    # 扣除双方亲密度 - 按百分比
    def DelIntimacyBothPer(self, aID, bID, delPer):
        for playerID, tagPlayerID in {aID:bID, bID:aID}.items():
            intimacys = self.GetIntimacys(playerID)
            if not intimacys:
                continue
            intimacyObj = intimacys.GetIntimacyObj(tagPlayerID)
            if not intimacyObj:
                continue
            curIntimacy = intimacyObj.Intimacy
            delValue = -max(1, int(curIntimacy * delPer / 100.0))
            curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
            updIntimacy = intimacys.AddIntimacy(curPlayer, tagPlayerID, delValue)
            GameWorld.DebugLog("扣除亲密度: playerID=%s,tagPlayerID=%s,curIntimacy=%s,delPer=%s,delValue=%s,updIntimacy=%s"
                               % (playerID, tagPlayerID, curIntimacy, delPer, delValue, updIntimacy), playerID)
        return
    # 获取亲密组
    def GetIntimacys(self, playerID):
        if playerID not in self.PlayerIntimacys:
            self.PlayerIntimacys[playerID] = Intimacys(playerID)
        return self.PlayerIntimacys[playerID]
    # 保存亲密数据 存数据库和realtimebackup
    def GetSaveData(self):
        savaData = ""
        cntData = ""
        cnt = 0
        for intimacys in self.PlayerIntimacys.values():
            for playerIntimacy in intimacys.SocialDict.values():
                cnt += 1
                savaData += playerIntimacy.getBuffer()
        GameWorld.Log("Save DBPyPlayerIntimacy cnt :%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 DBPyPlayerIntimacy cnt :%s"%cnt)
        self.PlayerIntimacys = {}
        for i in xrange(cnt):
            playerIntimacy = PyGameDataStruct.tagDBPyPlayerIntimacy()
            playerIntimacy.clear()
            pos += playerIntimacy.readData(datas, pos, dataslen)
            playerID = playerIntimacy.PlayerID
            if playerID not in self.PlayerIntimacys:
                self.PlayerIntimacys[playerID] = Intimacys(playerID)
            self.PlayerIntimacys[playerID].SocialDict[playerIntimacy.TagID] = playerIntimacy
            AddBeSocial(playerIntimacy.TagID, playerIntimacy.PlayerID)
        return pos
    
#-------------------仇人------------------------------
@@ -696,7 +795,6 @@
class SocialPlayerData(object):
    def __init__(self, playerSocial = None, player = None):
        self.playerInfo = PyGameDataStruct.tagPersonalSocial()
        self.syncMapCouple = 0 # 是否已经同步过地图全局伴侣信息
        
        if playerSocial:
            self.playerInfo = playerSocial
@@ -712,7 +810,6 @@
        self.playerInfo.LV = curPlayer.GetLV()
        self.playerInfo.RealmLV = curPlayer.GetOfficialRank()
        self.playerInfo.OnlineType = 1      # 0 不在线  1 在线 2 脱机在线  
        self.playerInfo.CoupleID = PlayerControl.GetCoupleID(curPlayer)
        if not self.playerInfo.RefCount:
            self.playerInfo.RefCount = 1
        return
@@ -725,38 +822,7 @@
        packStruct.LV = self.playerInfo.LV
        packStruct.RealmLV = self.playerInfo.RealmLV
        packStruct.OnlineType = self.playerInfo.OnlineType
        packStruct.CoupleID = self.GetCoupleID()
        return packStruct
    def GetCoupleID(self): return 0 if self.GetCoupleBreakOffline() else self.playerInfo.CoupleID
    def GetCoupleName(self): return "" if not self.GetCoupleID() else self.playerInfo.CoupleName
    def SetCoupleInfo(self, coupleID, coupleName):
        self.playerInfo.CoupleBreakOffline = 0
        self.playerInfo.CoupleID = coupleID
        self.playerInfo.CoupleName = coupleName
        Notify_All(self.playerInfo.PlayerID, IPY_PlayerDefine.CDBPlayerRefresh_ExAttr11, coupleID)
        return
    def GetBridePriceMaxID(self): return self.playerInfo.CouplePriceMaxID
    def CheckUpdCouplePriceMaxID(self, bridePriceID):
        if bridePriceID > 0 and bridePriceID <= self.playerInfo.CouplePriceMaxID:
            GameWorld.Log("不更新社交最高聘礼ID: bridePriceID=%s,self.playerInfo.CouplePriceMaxID=%s"
                          % (bridePriceID, self.playerInfo.CouplePriceMaxID), self.playerInfo.PlayerID)
            return
        self.playerInfo.CouplePriceMaxID = bridePriceID
        GameWorld.Log("更新社交最高聘礼ID: bridePriceID=%s" % (bridePriceID), self.playerInfo.PlayerID)
        return
    def GetCoupleBreakOffline(self):
        ## 是否离线状态下被离婚,等待下次上线处理
        return self.playerInfo.CoupleBreakOffline == 1
    def SetCoupleBreakOffline(self):
        ## 设置离线状态下被离婚,是的话将在玩家下次上线后处理解除相关伴侣关系,因为离线状态下无法处理,故做个标记等待上线处理
        self.playerInfo.CoupleBreakOffline = 1
        GameWorld.Log("离线状态下被离婚,标记伴侣社交关系已离婚!等下次上线处理! coupleID=%s" % self.playerInfo.CoupleID, self.playerInfo.PlayerID)
        return
    
    # 更新玩家数据引用, 根据需求是否更新玩家数据
    def AddSocialRef(self, curPlayer = None):
@@ -803,7 +869,6 @@
            playerSocial.LV = 1
            playerSocial.RealmLV = 1
            playerSocial.OnlineType = ChConfig.Def_Offline
            playerSocial.CoupleID = 0
        else:
            cacheDict = PlayerViewCache.GetCachePropDataDict(curCache)
    
@@ -814,7 +879,6 @@
            playerSocial.LV = cacheDict["LV"]
            playerSocial.RealmLV = cacheDict["RealmLV"]
            playerSocial.OnlineType = ChConfig.Def_Offline
            playerSocial.CoupleID = cacheDict.get("CoupleID", 0)
            
        self.SocialInfo[playerID] = SocialPlayerData(playerSocial)
        socialPlayer = self.SocialInfo[playerID]
@@ -831,11 +895,30 @@
        socialPlayer.SubSocialRef()
        if socialPlayer.GetRefCount() <= 0:
            self.SocialInfo.pop(delPlayerID)
    
    def GetSocialPlayer(self, playerID):
        return self.SocialInfo.get(playerID, None)
    
    def SyncSocialCoupleInfo(self, curPlayer):
        coupleMgr = PyDataManager.GetDBPyCoupleManager()
        coupleList = []
        for playerID in self.SocialInfo.keys():
            couple = coupleMgr.GetCouple(playerID)
            if not couple:
                continue
            socialCouple = ChPyNetSendPack.tagGCSocialCouple()
            socialCouple.PlayerID = playerID
            socialCouple.CoupleID = couple.GetCoupleID(playerID)
            coupleList.append(socialCouple)
        if not coupleList:
            return
        clientPack = ChPyNetSendPack.tagGCSocialCouples()
        clientPack.Player = coupleList
        clientPack.Count = len(clientPack.Player)
        NetPackCommon.SendFakePack(curPlayer, clientPack)
        return
    
    # 保存有社交的玩家信息
    def GetSaveData(self):
@@ -864,6 +947,38 @@
                
        return pos
def GetSocialPlayerName(playerID):
    ## 获取玩家社交昵称
    socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(playerID)
    if socialPlayer:
        return socialPlayer.playerInfo.PlayerName
    curCache = PlayerViewCache.FindViewCache(playerID)
    if curCache:
        cacheDict = PlayerViewCache.GetCachePropDataDict(curCache)
        return cacheDict["Name"]
    if playerID < 10000:
        return "testName%s" % playerID
    return ""
def GetSocialPlayerJob(playerID):
    ## 获取玩家社交职业
    socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(playerID)
    if socialPlayer:
        return socialPlayer.playerInfo.Job
    curCache = PlayerViewCache.FindViewCache(playerID)
    if curCache:
        cacheDict = PlayerViewCache.GetCachePropDataDict(curCache)
        return cacheDict["Job"]
    if playerID < 10000:
        job = 2 if playerID % 2 == 0 else 1
        return job
    return 1
# 向相关联的社交对象通知当前玩家信息
# 最近联系人、仇人和黑名单存在单向情况, 向对方通知信息
@@ -893,8 +1008,32 @@
        if PlayerControl.GetIsTJG(player):
            continue
        NetPackCommon.SendFakePack(player, pack)
    return
def NotifySocialCoupleChange(playerID, coupleID):
    ## 通知伴侣变更给相关社交人员
    if playerID not in PyGameData.g_BeSocialList:
        return
    couple = ChPyNetSendPack.tagGCSocialCouple()
    couple.PlayerID = playerID
    couple.CoupleID = coupleID
    clientPack = ChPyNetSendPack.tagGCSocialCouples()
    clientPack.Player.append(couple)
    clientPack.Count = len(clientPack.Player)
    for tagID in PyGameData.g_BeSocialList[playerID]:
        player = GameWorld.GetPlayerManager().FindPlayerByID(tagID)
        if not player:
            continue
        if PlayerControl.GetIsTJG(player):
            continue
        NetPackCommon.SendFakePack(player, clientPack)
    return
#更新玩家社交信息
def UpdateSocialInfo(playerID, notifyType, value):
@@ -908,39 +1047,8 @@
        socialPlayer.playerInfo.RealmLV = value
    elif notifyType == IPY_PlayerDefine.CDBPlayerRefresh_PlayerName:
        socialPlayer.playerInfo.PlayerName = value
        coupleID = socialPlayer.playerInfo.CoupleID
        if coupleID:
            coupleSocialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(coupleID)
            if coupleSocialPlayer:
                coupleSocialPlayer.playerInfo.CoupleName = value
                SendMapServerCoupleInfo([coupleID])
    Notify_All(playerID, notifyType, value)
    return
def SendMapServerCoupleInfo(syncPlayerIDList=None):
    checkState = False
    syncCoupleInfo = {}
    socialMgr = PyDataManager.GetPersonalSocialManager()
    if syncPlayerIDList == None:
        syncPlayerIDList = socialMgr.SocialInfo.keys()
        checkState = True # 未指定时才检查,防止启动地图时同步过多(启动地图时,只同步本次已经同步过的)
    for playerID in syncPlayerIDList:
        socialPlayer = socialMgr.GetSocialPlayer(playerID)
        if not socialPlayer:
            continue
        coupleID = socialPlayer.GetCoupleID()
        if checkState:
            if not socialPlayer.syncMapCouple:
                continue
            if not coupleID:
                continue
        socialPlayer.syncMapCouple = 1
        coupleName = socialPlayer.GetCoupleName()
        syncCoupleInfo[playerID] = [coupleID, coupleName] if coupleID else []
    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CoupleInfo, syncCoupleInfo)
    return
# 向当前玩家通知相关联的所有玩家信息
@@ -954,9 +1062,11 @@
    list3 = contacts.SocialDict.keys() if contacts else []
    blacklists = PyDataManager.GetBlacklistManager().GetBlacklist(playerID)
    list4 = blacklists.SocialDict.keys() if blacklists else []
    intimacys = PyDataManager.GetIntimacyManager().GetIntimacys(playerID)
    list5 = intimacys.SocialDict.keys() if intimacys else []
    #信息并集后发送, 玩家ID
    resultSet = set(list1)|set(list2)|set(list3)|set(list4)
    resultSet = set(list1)|set(list2)|set(list3)|set(list4)|set(list5)
    
    sendPack = ChPyNetSendPack.tagGCSocialPlayers()
    sendPack.Clear()
@@ -971,6 +1081,8 @@
        
    sendPack.Count = len(sendPack.Player)
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    socialManager.SyncSocialCoupleInfo(curPlayer)
    return