From ffa8a645ed6a92a3c723bbf5c7f1eb4d5425c826 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 17 十一月 2021 15:15:34 +0800
Subject: [PATCH] 9341 【BT5】【主干】【后端】情缘系统(优化情缘系统)

---
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py |  338 +++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 225 insertions(+), 113 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py
index 3ed29f5..6b70901 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerSocial.py
+++ b/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
     
 

--
Gitblit v1.8.0