ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py
@@ -26,7 +26,7 @@
import IpyGameDataPY
import PlayerViewCache
import PyGameData
import ShareDefine
#--------------------社交圈基本结构-------------------
# 社交圈
class SocialPlayers(object):
@@ -38,6 +38,9 @@
    
    # 添加社交对象
    def Add(self, tagID, isNotify=True):
        if not PlayerControl.GetDBPlayerAccIDByID(tagID):
            GameWorld.ErrLog("试图添加非本服玩家社交对象: tagID=%s,GroupType=%s" % (tagID, self.GroupType))
            return False
        GameWorld.DebugLog("SocialPlayers----Add %s-%s-%s"%(self.GroupType, self.PlayerID, tagID))
        if tagID in self.SocialDict:
            GameWorld.DebugLog("SocialPlayers----Add 重复")
@@ -99,6 +102,8 @@
    def GetCount(self):
        return len(self.SocialDict)
    
    def GetSocialIDList(self): return self.SocialDict.keys()
    def Find(self, tagID):
        return self.SocialDict.get(tagID, None)
    
@@ -122,20 +127,28 @@
    
    # 上线通知 
    def Sync_SocialsInfo(self, curPlayer):
    def Sync_SocialsInfo(self, curPlayer, playerIDList=None):
        if playerIDList == None:
            playerIDList = self.SocialDict.keys()
        pack = ChPyNetSendPack.tagGCGroupPlayers()
        pack.Clear()
        pack.GroupType = self.GroupType
        pack.Players = []
        pack.Count = self.GetCount()
        
        for player in self.SocialDict.values():
        for playerID in playerIDList:
            if playerID not in self.SocialDict:
                continue
            player = self.SocialDict[playerID]
            inPack = ChPyNetSendPack.tagGCGroupPlayer()
            inPack.PlayerID = player.TagID
            
            inPack.SortValue = player.Timestamp if hasattr(player, 'Timestamp') 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)
        NetPackCommon.SendFakePack(curPlayer, pack)
        return
@@ -147,7 +160,10 @@
        sendPack.Count = 1
        sendPack.Player = []
        socialManager = PyDataManager.GetPersonalSocialManager()
        socialInfo = socialManager.GetSocialPlayer(tagID).GetPackStruct(ChPyNetSendPack.tagGCSocialPlayer())
        socialPlayer = socialManager.GetSocialPlayer(tagID)
        if not socialPlayer:
            return
        socialInfo = socialPlayer.GetPackStruct(ChPyNetSendPack.tagGCSocialPlayer())
        sendPack.Player.append(socialInfo)
            
        NetPackCommon.SendFakePack(curPlayer, sendPack)
@@ -185,23 +201,25 @@
        self.Delete(delFriendID)
        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(self.PlayerID)
        self.MapServer_SyncFriendInfo(curPlayer)
    # 通知地图好友信息
    def MapServer_SyncFriendInfo(self, curPlayer):
        if not curPlayer:
            return
        sendPack = ChGameToMapPyPack.tagGMFriendInfo()
        sendPack.PlayerID = curPlayer.GetPlayerID()
        sendPack.FriendCnt = self.GetCount()
        sendPack.Friends = []
        return
        #=======================================================================
        # if not curPlayer:
        #    return
        # sendPack = ChGameToMapPyPack.tagGMFriendInfo()
        # sendPack.PlayerID = curPlayer.GetPlayerID()
        # sendPack.FriendCnt = self.GetCount()
        # sendPack.Friends = []
        #
        # for friendInfo in self.SocialDict.values():
        #    playerFriend = ChGameToMapPyPack.tagGMPlayerFrendInfo()
        #    playerFriend.TagID = friendInfo.TagID
        #    sendPack.Friends.append(playerFriend)
        # NetPackCommon.SendPyPackToMapServer(curPlayer.GetLineNO(), curPlayer.GetRealMapID(), sendPack)
        #=======================================================================
        
        for friendInfo in self.SocialDict.values():
            playerFriend = ChGameToMapPyPack.tagGMPlayerFrendInfo()
            playerFriend.TagID = friendInfo.PlayerID
            sendPack.Friends.append(playerFriend)
        NetPackCommon.SendPyPackToMapServer(curPlayer.GetLineNO(), curPlayer.GetRealMapID(), sendPack)
# 整个游戏的好友管理
class FriendManager(object):
@@ -261,7 +279,7 @@
                cnt += 1
                savaData += friend.getBuffer()
        
        GameWorld.Log("SaveFriendData cnt :%s"%cnt)
        GameWorld.Log("SaveFriendData cnt :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
    # 从数据库载入好友数据
@@ -280,6 +298,172 @@
            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
        self.__SyncMapServerCoupleIntimacy(curPlayer, tagID)
        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.__SyncMapServerCoupleIntimacy(curPlayer, tagID)
            self.Sync_SocialsInfo(curPlayer, [tagID])
        return intimacyObj.Intimacy
    def __SyncMapServerCoupleIntimacy(self, curPlayer, tagID):
        ## 同步地图玩家伴侣亲密度
        playerID = curPlayer.GetPlayerID()
        couple = PyDataManager.GetDBPyCoupleManager().GetCouple(playerID)
        if not couple:
            return
        if couple.GetCoupleID(playerID) != tagID:
            return
        self.SyncMapServerIntimacy(curPlayer, tagID)
        return
    def SyncMapServerIntimacy(self, curPlayer, tagID):
        ## 同步地图玩家伴侣亲密度
        playerID = curPlayer.GetPlayerID()
        intimacyValue = 0
        intimacyObj = self.GetIntimacyObj(tagID)
        if intimacyObj:
            intimacyValue = intimacyObj.Intimacy
        cmdInfo = ["SyncMapServerIntimacy", [tagID, intimacyValue]]
        PlayerControl.MapServer_QueryPlayer_DoLogic(curPlayer, "Love", cmdInfo, playerID)
        return
# 整个游戏的亲密管理
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 not PlayerControl.GetDBPlayerAccIDByID(playerID):
            GameWorld.ErrLog("试图获取非本服玩家亲密组: playerID=%s" % playerID)
            return
        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
    
#-------------------仇人------------------------------
@@ -378,7 +562,7 @@
                cnt += 1
                savaData += socialPlayer.getBuffer()
        
        GameWorld.Log("!!SaveEnemyData cnt :%s"%cnt)
        GameWorld.Log("!!SaveEnemyData cnt :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
    # 从数据库载入
@@ -534,7 +718,7 @@
                cnt += 1
                savaData += socialPlayer.getBuffer()
        
        GameWorld.Log("!!SaveContactsData cnt :%s"%cnt)
        GameWorld.Log("!!SaveContactsData cnt :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
    # 从数据库载入
@@ -615,7 +799,7 @@
                cnt += 1
                savaData += socialPlayer.getBuffer()
        
        GameWorld.Log("!!SaveBlacklistData cnt :%s"%cnt)
        GameWorld.Log("!!SaveBlacklistData cnt :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
    # 从数据库载入
@@ -657,6 +841,8 @@
        self.playerInfo.LV = curPlayer.GetLV()
        self.playerInfo.RealmLV = curPlayer.GetOfficialRank()
        self.playerInfo.OnlineType = 1      # 0 不在线  1 在线 2 脱机在线  
        self.playerInfo.Face = curPlayer.GetFace()
        self.playerInfo.FacePic = curPlayer.GetFacePic()
        if not self.playerInfo.RefCount:
            self.playerInfo.RefCount = 1
        return
@@ -669,8 +855,9 @@
        packStruct.LV = self.playerInfo.LV
        packStruct.RealmLV = self.playerInfo.RealmLV
        packStruct.OnlineType = self.playerInfo.OnlineType
        packStruct.Face = self.playerInfo.Face
        packStruct.FacePic = self.playerInfo.FacePic
        return packStruct
    
    # 更新玩家数据引用, 根据需求是否更新玩家数据
    def AddSocialRef(self, curPlayer = None):
@@ -706,7 +893,7 @@
        
    # 增加社交对象信息,针对不在社交圈记录并且不在线玩家的情况
    def AddPlayerInfoByViewCache(self, playerID):
        curCache = PlayerViewCache.ViewCacheMgr.FindCache(playerID)
        curCache = PlayerViewCache.FindViewCache(playerID)
        playerSocial = PyGameDataStruct.tagPersonalSocial()
        if not curCache:
            # 实在找不到设置为初始化数据
@@ -717,8 +904,10 @@
            playerSocial.LV = 1
            playerSocial.RealmLV = 1
            playerSocial.OnlineType = ChConfig.Def_Offline
            playerSocial.Face = 0
            playerSocial.FacePic = 0
        else:
            cacheDict = eval(curCache.GetPropData())
            cacheDict = PlayerViewCache.GetCachePropDataDict(curCache)
    
            playerSocial.clear()
            playerSocial.PlayerID = playerID
@@ -727,6 +916,8 @@
            playerSocial.LV = cacheDict["LV"]
            playerSocial.RealmLV = cacheDict["RealmLV"]
            playerSocial.OnlineType = ChConfig.Def_Offline
            playerSocial.Face = cacheDict.get("Face", 0)
            playerSocial.FacePic = cacheDict.get("FacePic", 0)
            
        self.SocialInfo[playerID] = SocialPlayerData(playerSocial)
        socialPlayer = self.SocialInfo[playerID]
@@ -743,22 +934,44 @@
        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):
        savaData = ""
        cntData = ""
        cnt = 0
        for socialPlayer in self.SocialInfo.values():
        for playerID, socialPlayer in self.SocialInfo.items():
            if PyGameData.g_dbPlayerIDMap and not PlayerControl.GetDBPlayerAccIDByID(playerID):
                GameWorld.ErrLog("非本服社交玩家,不存档! playerID=%s" % playerID)
                continue
            cnt += 1
            savaData += socialPlayer.playerInfo.getBuffer()
        
        GameWorld.Log("SaveSocialData cnt :%s"%cnt)
        GameWorld.Log("SaveSocialData cnt :%s len=%s" % (cnt, len(savaData)))
        return CommFunc.WriteDWORD(cntData, cnt) + savaData
@@ -776,6 +989,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
# 向相关联的社交对象通知当前玩家信息
# 最近联系人、仇人和黑名单存在单向情况, 向对方通知信息
@@ -805,12 +1050,36 @@
        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(curPlayer, notifyType, value):
    socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(curPlayer.GetID())
def UpdateSocialInfo(playerID, notifyType, value):
    socialPlayer = PyDataManager.GetPersonalSocialManager().GetSocialPlayer(playerID)
    if socialPlayer == None:
        return
    
@@ -820,10 +1089,15 @@
        socialPlayer.playerInfo.RealmLV = value
    elif notifyType == IPY_PlayerDefine.CDBPlayerRefresh_PlayerName:
        socialPlayer.playerInfo.PlayerName = value
    Notify_All(curPlayer.GetID(), notifyType, value)
    elif notifyType == IPY_PlayerDefine.CDBPlayerRefresh_Face:
        socialPlayer.playerInfo.Face = value
    elif notifyType == IPY_PlayerDefine.CDBPlayerRefresh_HairColor:
        socialPlayer.playerInfo.FacePic = value
    else:
        return
    Notify_All(playerID, notifyType, value)
    return
# 向当前玩家通知相关联的所有玩家信息
def Sync_AllSocialsInfo(curPlayer):
@@ -836,9 +1110,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()
@@ -853,6 +1129,8 @@
        
    sendPack.Count = len(sendPack.Player)
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    socialManager.SyncSocialCoupleInfo(curPlayer)
    return