hxp
2025-05-23 fdebf36f0d9201c6a6949a08cdfeebb718c25ce2
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTalk.py
@@ -1,268 +1,110 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package
##@package Player.PlayerTalk
#
# @todo: 玩家聊天逻辑 支持语音
#
# @author: Alee
# @date 2018-4-24 下午07:36:28
# @todo:聊天
# @author hxp
# @date 2025-05-23
# @version 1.0
#
# @note:
# 详细描述: 聊天
#
#---------------------------------------------------------------------
import IPY_GameWorld
import GameWorld
import PlayerControl
#-------------------------------------------------------------------------------
#"""Version = 2025-05-23 20:00"""
#-------------------------------------------------------------------------------
import ChConfig
import FBLogic
#import ReadChConfig
import GameWorld
import ShareDefine
import IPY_GameWorld
import ChPyNetSendPack
import CrossRealmPlayer
import PlayerViewCache
import NetPackCommon
import EventReport
import PlayerSuccess
import IpyGameDataPY
import ItemCommon
import ChItem
import PlayerTJG
import EventShell
import PyGameData
import PlayerLove
import PlayerControl
import PlayerFamily
import DBDataMgr
import math
#---------------------------------------------------------------------
#需要记录聊天缓存的频道对应限制最大条数
ChannelCacheMax = {IPY_GameWorld.tcFamily:30,
                   IPY_GameWorld.tcWorld:100,
                   }
def OnPlayerLogin(curPlayer):
    NotifyTalkCache(curPlayer)
    return
## 区域频道(封包参数)
#  @param index 玩家索引
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
#  整个地图的人都可以听到
def TalkArea(index, tick):
#// B3 20 聊天 #tagCMTalk
#
#struct    tagCMPyTalk
#{
#    tagHead        Head;
#    BYTE        ChannelType;    // 频道
#    WORD        Len;
#    char        Content[Len];        //size = Len
#};
def OnTalk(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    familyID = curPlayer.GetFamilyID()
    channelType = clientData.ChannelType
    content = clientData.Content
    
    #获得区域频封包
    sendPack = IPY_GameWorld.IPY_CTalkArea()
    #玩家聊天内容
    content = sendPack.GetContent()
    #通用判断
    if not __CheckTalk(curPlayer, content, sendPack.GetLen(), tick, talkType=IPY_GameWorld.tcArea):
        return
    #通用设置
    SetTalkTime(curPlayer, content, IPY_GameWorld.tcArea, tick)
    #如果在普通地图, 就广播, 如果在副本就单个通知
    if GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtNull and not GameWorld.IsCrossServer():
        #广播
        extras = GetTalkExtraValue(curPlayer)
        curPlayer.ChatArea(content, 0, extras)
    else:
        __DoLogic_FB_TalkArea(curPlayer, content)
    return True
## 副本中说话
#  @param curPlayer 当前玩家
#  @param content 讲话的内容
#  @return None
#  @remarks 函数详细说明.
def __DoLogic_FB_TalkArea(curPlayer, content):
    playerManager = GameWorld.GetMapCopyPlayerManager()
    for index in range(0 , playerManager.GetPlayerCount()):
        #广播玩家
        tempPlayer = playerManager.GetPlayerByIndex(index)
        if not tempPlayer.GetPlayerID():
            continue
    #GameWorld.DebugLog("OnTalk channelType=%s, %s" % (channelType, GameWorld.CodeToGbk(content)))
    if channelType == IPY_GameWorld.tcFamily:
        if not familyID:
            PlayerControl.NotifyCode(curPlayer, "jiazu_lhs_0")
            return
        
        #单个广播说话
        extras = GetTalkExtraValue(curPlayer)
        tempPlayer.Sync_ChatArea(curPlayer.GetPlayerID(), content, 0, extras)
    elif channelType == IPY_GameWorld.tcCountry:
        if GameWorld.IsCrossServer():
            return
        if not CrossRealmPlayer.IsCrossServerOpen():
            PlayerControl.NotifyCode(curPlayer, "CrossMatching18")
            return
        
    if not __CheckTalk(curPlayer, channelType, content, tick):
        return
    curPlayer.SetLastChatTick(tick)
    curPlayer.SetDict(ChConfig.Def_ChannelTalkTick % channelType, tick)
    if channelType == IPY_GameWorld.tcCountry:
        #发送到跨服,待扩展
        return
    bubbleBox = PlayerControl.GetChatBubbleBox(curPlayer) # 气泡框
    clientPack = ChPyNetSendPack.tagMCTalk()
    clientPack.ChannelType = channelType
    clientPack.PlayerID = playerID
    clientPack.Name = curPlayer.GetPlayerName()
    clientPack.NameLen = len(clientPack.Name)
    clientPack.Content = content
    clientPack.Len = len(clientPack.Content)
    clientPack.BubbleBox = bubbleBox
    clientPack.LV = curPlayer.GetLV()
    clientPack.Job = curPlayer.GetJob()
    clientPack.RealmLV = curPlayer.GetOfficialRank()
    clientPack.Face = curPlayer.GetFace()
    clientPack.FacePic = curPlayer.GetFacePic()
    clientPack.ServerID = GameWorld.GetPlayerServerID(curPlayer)
    if channelType == IPY_GameWorld.tcWorld:
        NetPackCommon.SendFackPackOnline(clientPack)
    elif channelType == IPY_GameWorld.tcFamily:
        PlayerFamily.Broadcast_FamilyPack(familyID, clientPack)
    DoTalkCache(channelType, playerID, content, bubbleBox, familyID)
    return
## 世界频道(封包参数)
#  @param index 玩家索引
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def TalkWorld(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    sendPack = IPY_GameWorld.IPY_CTalkGong()
    #玩家聊天内容
    content = sendPack.GetContent()
    #通用检测
    if not __CheckTalk(curPlayer, content, sendPack.GetLen(), tick, checkSameMsg = False, talkType=IPY_GameWorld.tcWorld):
        return
    #通用设置
    SetTalkTime(curPlayer, content, IPY_GameWorld.tcWorld, tick)
    #发送聊天内容
    extras = GetTalkExtraValue(curPlayer)
    curPlayer.ChatGong(content, 0, extras)
    #世界频道发言成就
    #PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_TalkWorld, 1)
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FeastRedPack_TalkWorld, 1)
    EventShell.EventRespons_Talk(curPlayer, 'talkworld')
    return
## 国家频道(封包参数)
#  @param index 玩家索引
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def TalkCountry(index, tick):
    ## 跨服世界频道
    if GameWorld.IsCrossServer():
        return
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    if not CrossRealmPlayer.IsCrossServerOpen():
        PlayerControl.NotifyCode(curPlayer, "CrossMatching18")
        return
    sendPack = IPY_GameWorld.IPY_CTalkCountry()
    #玩家聊天内容
    content = sendPack.GetContent()
    #通用检测
    if not __CheckTalk(curPlayer, content, sendPack.GetLen(), tick, checkSameMsg = False, talkType=IPY_GameWorld.tcCountry):
        return
    #通用设置
    SetTalkTime(curPlayer, content, IPY_GameWorld.tcCountry, tick)
    #发送聊天内容
    extras = GetTalkExtraValue(curPlayer)
    curPlayer.ChatCountry(content, 0, extras)
    return
## 联盟家族频道(封包参数)
#  @param index 玩家索引
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def TalkFamily(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    if curPlayer.GetFamilyID() == 0:
        PlayerControl.NotifyCode(curPlayer, "jiazu_lhs_0 ")
        return
    sendPack = IPY_GameWorld.IPY_CTalkBang()
    #玩家聊天内容
    content = sendPack.GetContent()
    if not __CheckTalk(curPlayer, content, sendPack.GetLen(), tick, talkType=IPY_GameWorld.tcFamily):
        return
    #通用设置
    SetTalkTime(curPlayer, content, IPY_GameWorld.tcFamily, tick)
    extras = GetTalkExtraValue(curPlayer)
    curPlayer.ChatFamily(content, 0, extras)
    #仙盟频道发言成就
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_TalkFamily, 1)
    EventShell.EventRespons_Talk(curPlayer, 'talkfamily')
    return
## 队伍频道(封包参数)
#  @param index 玩家索引
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def TalkTeam(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    if curPlayer.GetTeam() == None:
        PlayerControl.NotifyCode(curPlayer, "GeRen_lhs_161795 ")
        return
    sendPack = IPY_GameWorld.IPY_CTalkDui()
    #玩家聊天内容
    content = sendPack.GetContent()
    if not __CheckTalk(curPlayer, content, sendPack.GetLen(), tick, talkType=IPY_GameWorld.tcTeam):
        return
    #通用设置
    SetTalkTime(curPlayer, content, IPY_GameWorld.tcTeam, tick)
    #说话
    extras = GetTalkExtraValue(curPlayer)
    curPlayer.ChatTeam(content, 0, extras)
    return
## 私聊频道(封包参数)
#  @param index 玩家索引
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def TalkPrivate(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    sendPack = IPY_GameWorld.IPY_CTalkMiFix()
    #玩家聊天内容
    content = sendPack.GetContent()
    if not __CheckTalk(curPlayer, content, sendPack.GetLen(), tick, talkType=IPY_GameWorld.tcPrivate):
        return
    #通用设置
    SetTalkTime(curPlayer, content, IPY_GameWorld.tcPrivate, tick)
    #说话
    extras = GetTalkExtraValue(curPlayer)
    curPlayer.ChatMiByID(sendPack.GetTalkType(), sendPack.GetPlayerID(), content, 0, extras)
    return
def TalkPrivateByID(curPlayer, tagPlayerID, content):
    #私聊 0为默认 1为1对1聊天
    talkType = 1
    extras = GetTalkExtraValue(curPlayer)
    curPlayer.ChatMiByID(talkType, tagPlayerID, content, 0, extras)
    return
## 私聊频道(封包参数)
#  @param index 玩家索引
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def TalkPrivateName(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    sendPack = IPY_GameWorld.IPY_CTalkMi()
    #玩家聊天内容
    content = sendPack.GetContent()
    if not __CheckTalk(curPlayer, content, sendPack.GetLen(), tick, talkType=IPY_GameWorld.tcPrivate):
        return
    #通用设置
    SetTalkTime(curPlayer, content, IPY_GameWorld.tcPrivate, tick)
    #说话
    extras = GetTalkExtraValue(curPlayer)
    curPlayer.ChatMiByName(sendPack.GetTalkType(), sendPack.GetTargetName(), content, 0, extras)
    return
#-3秒重复,;聊天信息太长
## 聊天通用检查
#  @param curPlayer 当前玩家
#  @param content 聊天内容
#  @param length 聊天长度
#  @param tick 当前时间
#  @param checkGMForbidenTalk 检查是否禁言
#  @param checkSameMsg 是否检查相同信息
#  @return True or False
#  @remarks 函数详细说明.
def __CheckTalk(curPlayer, content, length, tick, checkGMForbidenTalk = True, checkSameMsg = True, talkType=None):
def __CheckTalk(curPlayer, channelType, content, tick, checkGMForbidenTalk=True):
    ## 聊天通用检查
    if checkGMForbidenTalk and GetGMToolForbidTalk(curPlayer):
        #GeRen_chenxin_921745 对不起,您已被GM禁言,发送信息失败
        #PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_921745")
@@ -274,18 +116,18 @@
        return False
    
    #频道各自间隔时间
    if talkType != None:
    if channelType != None:
        talkCDDict = IpyGameDataPY.GetFuncEvalCfg("TalkCD", 1, {})
        if str(talkType) in talkCDDict:
            cdTicks = talkCDDict[str(talkType)] * 1000
            lastTalkTick = curPlayer.GetTalkTick(talkType)
        if str(channelType) in talkCDDict:
            cdTicks = talkCDDict[str(channelType)] * 1000
            lastTalkTick = curPlayer.GetDictByKey(ChConfig.Def_ChannelTalkTick % channelType)
            remainTick = cdTicks - (tick - lastTalkTick)
            if remainTick > 0:
                PlayerControl.NotifyCode(curPlayer, "CanootTalk01", [int(math.ceil(remainTick/1000.0))])
                PlayerControl.NotifyCode(curPlayer, "CanootTalk01", [int(math.ceil(remainTick / 1000.0))])
                return False
            
    #聊天信息太长
    if length > ChConfig.Def_PlayerTalkMaxCount :
    if len(content) > ChConfig.Def_PlayerTalkMaxCount:
        PlayerControl.NotifyCode(curPlayer, "CanootTalk13")
        return False
    
@@ -296,315 +138,97 @@
    
    return True
## 获得玩家是否被禁言
#  @param curPlayer 当前玩家
#  @return 是否禁言
def GetGMToolForbidTalk(curPlayer):
    ## 获得玩家是否被禁言
    #accIDForbid = (curPlayer.GetAccState() & pow(2, ChConfig.Def_PysForbidTalk)) > 0
    return curPlayer.GetGMForbidenTalk()# or accIDForbid
## 聊天时间通用设置
#  @param curPlayer 当前玩家
#  @param content 聊天内容
#  @param type 类型
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def SetTalkTime(curPlayer, content, type, tick):
    #设置当前时间为玩家开始聊天时间
    curPlayer.SetLastChatTick(tick)
    #设置当前聊天内容为玩家本次聊天内容
    #curPlayer.SetLastChatContent(content)
    #设置当前频道时间
    curPlayer.SetTalkTick(type, tick)
    return
## 信件2B封包
#  @param index 玩家索引
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def GBLetter(index, tick):
    #===========================================================================
    # curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    # sendPack = IPY_GameWorld.IPY_CGBLetter()
    #
    # if tick - curPlayer.GetTickByType(ChConfig.TYPE_Player_Tick_GBLetter) <= ChConfig.TYPE_Player_Tick_Time[ChConfig.TYPE_Player_Tick_GBLetter]:
    #    #发信1秒间隔
    #    return
    #
    # curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_GBLetter, tick)
    #
    # #信件标题和内容
    # titleStr = sendPack.GetTitle()
    # contentStr = sendPack.GetContent()
    #
    # #发给GM
    # curPlayer.Interface_SendGMLetter(titleStr, contentStr)
    #===========================================================================
    return
## 记录玩家聊天内容
#  @param messageStr 聊天类型
#  @param curPlayer 聊天的玩家
#  @param tagPlayer None
#  @param content 聊天内容
#  @param addinfo 额外信息
#  @return None
#  @remarks 函数详细说明.
def __LogInDBPlayerTalk(messageStr , curPlayer , tagPlayer , content, addinfo=""):
    # 由客户端向后台发送
    return
    #===========================================================================
    # tagName = "" if not tagPlayer else tagPlayer.GetName()
    # #EventReport.WriteEvent_chat_log(curPlayer, content, messageStr, tagName, addinfo)
    # gameWorld = GameWorld.GetGameWorld()
    # #开关未开启
    # if not gameWorld.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_PurTalk):
    #    return
    #
    # #将聊天内容存入数据库
    # gameWorld.DataServer_TalkTrace('%s'%(messageStr), curPlayer, tagPlayer, content)
    # return
    #===========================================================================
## 获取聊天内容附加值
#  @param objTalk: 聊天对象
#  @return: 聊天内容附加值
def GetTalkExtraValue(objTalk):
    vipLv = objTalk.GetVIPLv()  # 玩家vip等级
    GMLevel = objTalk.GetGMLevel()
    job = objTalk.GetJob()
    playerID = objTalk.GetID()
    extraValueStr = ""
    # vip等级
    extraValueStr += GetTalkExtraValueStar(ShareDefine.Def_TalkExtraValue_Bit_VipLv)%vipLv
    # GM
    extraValueStr += GetTalkExtraValueStar(ShareDefine.Def_TalkExtraValue_Bit_GM)% (GMLevel > 0)
    # job
    extraValueStr += GetTalkExtraValueStar(ShareDefine.Def_TalkExtraValue_Bit_JOB)% job
    # 气泡框
    extraValueStr += GetTalkExtraValueStar(ShareDefine.Def_TalkExtraValue_Bit_BubbleBox) % PlayerControl.GetChatBubbleBox(objTalk)
    # 服务器组ID
    extraValueStr += GetTalkExtraValueStar(ShareDefine.Def_TalkExtraValue_Bit_ServerGroupID) % PlayerControl.GetPlayerServerGroupID(objTalk)
    # 等级
    extraValueStr += GetTalkExtraValueStar(ShareDefine.Def_TalkExtraValue_Bit_LV) % objTalk.GetLV()
    # 伴侣信息
    coupleName = PlayerControl.GetCoupleName(objTalk)
    coupleJob = PlayerControl.GetCoupleJob(objTalk)
    bridePriceMaxID = PlayerControl.GetBridePriceMaxID(objTalk)
    face = objTalk.GetFace()
    facePic = objTalk.GetFacePic()
    extraValueStr = "%s|%s|%s|%s|%s|%s" % (extraValueStr, coupleName, coupleJob, bridePriceMaxID, face, facePic)
    return extraValueStr
## 附加信息的长度匹配
#  @param extraValueInfo: 附加信息的长度
#  @return:
def GetTalkExtraValueStar(extraValueType):
    extraValueInfo = ShareDefine.Def_TalkExtraValue_LenDict.get(extraValueType)
    extraValueLen = extraValueInfo[1] - extraValueInfo[0]
    return "%0" + str(extraValueLen) + "d"
#// A2 17 喇叭聊天 #tagCMPYSpeaker
#
#struct    tagCMPYSpeaker
#{
#    tagHead        Head;
#    BYTE        SpeakerType;        //1-本服;2-跨服
#    BYTE        IsUseGold;        //是否使用钻石
#    BYTE        ItemIndex;        //使用物品说话时, 物品Index
#    BYTE        TextLen;        //字符长度
#    char        Text[TextLen];        //size = TextLen
#};
def OnUsePYSpeaker(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    SpeakerType = clientData.SpeakerType
    IsUseGold = clientData.IsUseGold
    ItemIndex = clientData.ItemIndex
    TextLen = clientData.TextLen
    Text = clientData.Text
    #GameWorld.Log("玩家喇叭聊天: SpeakerType=%s,IsUseGold=%s,ItemIndex=%s"
    #              % (SpeakerType, IsUseGold, ItemIndex), playerID)
    if not __CheckTalk(curPlayer, Text, TextLen, tick):
def DoTalkCache(channelType, playerID, content, bubbleBox, familyID=0):
    # 聊天缓存
    if channelType not in ChannelCacheMax:
        return
    cacheMaxDict = IpyGameDataPY.GetFuncEvalCfg("TalkCache", 1, {})
    maxCount = min(ChannelCacheMax[channelType], cacheMaxDict.get(channelType, 0))
    
    if IsUseGold:
        bugleItemID = IpyGameDataPY.GetFuncCfg('BugleItem', SpeakerType)
        if not bugleItemID:
            GameWorld.ErrLog("功能配置表没有配置对应喇叭类型物品消耗!SpeakerType=%s,请检查BugleItem!" % SpeakerType)
            return
        costMoney = ItemCommon.GetAutoBuyItemNeedGold({bugleItemID:1})
        if not costMoney:
            return
        moneyType = IPY_GameWorld.TYPE_Price_Gold_Money
        infoDict = {"SpeakerType":SpeakerType, ChConfig.Def_Cost_Reason_SonKey:bugleItemID}
        if not PlayerControl.PayMoney(curPlayer, moneyType, costMoney, ChConfig.Def_Cost_UseSpeaker, infoDict, 1):
            return
    # 检查使用喇叭道具
    elif not ChItem.DoSpeaker_UseItem(curPlayer, ItemIndex, SpeakerType):
        GameWorld.Log("    喇叭道具不可用!", playerID)
        return
    #通知世界服务器,使用小喇叭
    extraValue = 0
    extras = GetTalkExtraValue(curPlayer)
    msgList = str([SpeakerType, Text, extraValue, extras])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, 'PYSpeaker', msgList, len(msgList))
    return
#// A2 16 自定义玩家聊天 #tagCMPyTalk
#
#struct    tagCMPyTalk
#{
#    tagHead        Head;
#    BYTE        TalkType;        // 自定义聊天类型
#    WORD        Len;
#    char        Content[Len];        //size = Len
#};
## 自定义玩家聊天
#  @param index
#  @param clientData
#  @param tick
#  @return
def OnPyTalk(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    #GameWorld.DebugLog("OnPyTalk, Name:%s" % curPlayer.GetPlayerName())
    talkType = clientData.TalkType
    contentLen = clientData.Len
    content = clientData.Content
    if talkType not in ShareDefine.TalkTypeList:
        GameWorld.ErrLog("OnPyTalk talkType(%s) is not define!" % talkType, curPlayer.GetPlayerID())
        return
    #通用判断
    if not __CheckTalk(curPlayer, content, contentLen, tick):
        return
    #说话
    extraValue = 0
    extras = GetTalkExtraValue(curPlayer)
    isChatOK = False
    if talkType == ShareDefine.Def_TalkType_FBFaction:
        isChatOK = __ChatFBFaction(curPlayer, talkType, content, extraValue, extras)
    # 仙盟聊天存FamilyAction
    if channelType == IPY_GameWorld.tcFamily:
        familyActonMgr = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, ShareDefine.Def_ActionType_TalkCache)
        actionData = familyActonMgr.AddAction(maxCount)
        actionData.SetValue1(playerID)
        actionData.SetValue2(bubbleBox)
        actionData.GetUserDict().update({"content":content})
        
    if not isChatOK:
        return
    #设置当前时间为玩家开始聊天时间
    curPlayer.SetLastChatTick(tick)
    #设置当前聊天内容为玩家本次聊天内容
    curPlayer.SetLastChatContent(content)
    return True
    else:
        recTypeIDMgr = DBDataMgr.GetGameRecMgr().GetRecTypeIDMgr(ShareDefine.Def_GameRecType_TalkCache, channelType)
        recData = recTypeIDMgr.AddRecData(maxCount)
        recData.SetValue1(playerID)
        recData.SetValue2(bubbleBox)
        recData.GetUserDict().update({"content":content})
    return
## py自定义聊天推送包
def __GetPyTalkPack(curPlayer, talkType, content, extraValue, extras):
    pyTalk = ChPyNetSendPack.tagMCPyTalk()
    pyTalk.Clear()
    pyTalk.TalkType = talkType
    pyTalk.Name = curPlayer.GetPlayerName()
    pyTalk.NameLen = len(pyTalk.Name)
    pyTalk.PlayerID = curPlayer.GetPlayerID()
    pyTalk.Len = len(content)
    pyTalk.Content = content
    pyTalk.ExtraValue = extraValue
    pyTalk.Extras = extras
    return pyTalk
## 副本阵营聊天
def __ChatFBFaction(curPlayer, talkType, content, extraValue, extras):
    curFaction = curPlayer.GetFaction()
    if not curFaction:
        return False
def NotifyTalkCache(curPlayer):
    ##上线通知聊天缓存
    
    pyTalkPack = __GetPyTalkPack(curPlayer, talkType, content, extraValue, extras)
    playerManager = GameWorld.GetMapCopyPlayerManager()
    for index in range(playerManager.GetPlayerCount()):
        player = playerManager.GetPlayerByIndex(index)
        if not player:
    for channelType in ChannelCacheMax.keys():
        cacheList = []
        if channelType == IPY_GameWorld.tcFamily:
            familyID = curPlayer.GetFamilyID()
            if not familyID:
                continue
            familyActonMgr = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, ShareDefine.Def_ActionType_TalkCache)
            for index in range(familyActonMgr.Count()):
                actionData = familyActonMgr.At(index)
                talkTime = actionData.GetTime()
                playerID = actionData.GetValue1()
                bubbleBox = actionData.GetValue2()
                content = actionData.GetUserDict().get("content", "")
                if not content:
                    content
                cacheList.append([talkTime, playerID, bubbleBox, content])
        else:
            recTypeIDMgr = DBDataMgr.GetGameRecMgr().GetRecTypeIDMgr(ShareDefine.Def_GameRecType_TalkCache, channelType)
            for index in range(recTypeIDMgr.GetCount()):
                recData = recTypeIDMgr.At(index)
                talkTime = recData.GetTime()
                playerID = recData.GetValue1()
                bubbleBox = recData.GetValue2()
                content = recData.GetUserDict().get("content", "")
                if not content:
                    content
                cacheList.append([talkTime, playerID, bubbleBox, content])
        if not cacheList:
            continue
        
        if player.GetFaction() != curFaction:
        packCacheList = []
        for talkTime, playerID, bubbleBox, content in cacheList:
            viewCache = PlayerViewCache.FindViewCache(playerID)
            if not viewCache:
                continue
            talkCache = ChPyNetSendPack.tagMCTalkCacheInfo()
            talkCache.PlayerID = playerID
            talkCache.Name = viewCache.GetPlayerName()
            talkCache.NameLen = len(talkCache.Name)
            talkCache.Content = content
            talkCache.Len = len(talkCache.Content)
            talkCache.BubbleBox = bubbleBox
            talkCache.LV = viewCache.GetLV()
            talkCache.Job = viewCache.GetJob()
            talkCache.RealmLV = viewCache.GetRealmLV()
            talkCache.Face = viewCache.GetFace()
            talkCache.FacePic = viewCache.GetFacePic()
            talkCache.ServerID = viewCache.GetServerID()
            talkCache.TalkTime = talkTime
            packCacheList.append(talkCache)
        if not packCacheList:
            continue
        
        if PlayerTJG.GetIsTJG(player):
            continue
        clientPack = ChPyNetSendPack.tagMCTalkCacheList()
        clientPack.ChannelType = channelType
        clientPack.InfoList = packCacheList
        clientPack.Count = len(clientPack.InfoList)
        NetPackCommon.SendFakePack(curPlayer, clientPack)
        
        NetPackCommon.SendFakePack(player, pyTalkPack)
    return True
#===============================================================================
# //A2 26 语音聊天 #tagCMVoiceChat
#
# struct    tagCMVoiceChat
# {
#    tagHead        Head;
#    BYTE        ChannelType;     //  5 区域 --- 查看封包tagCGVoiceChat 1 世界 2 仙盟 3 私聊(好友) 4 队伍
#    BYTE        TargetNameLen;
#    char        TargetName[TargetNameLen];        //size = TargetNameLen
#    DWORD        TargetID;        // 默认发玩家ID,没有ID才发名称
#    WORD        Len;
#    BYTE        Content[Len];        //size = Len
# };
#===============================================================================
def OnVoiceChat(index, clientPack, tick):
#    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
#    if GetGMToolForbidTalk(curPlayer):
#        return
#    if clientPack.ChannelType != ShareDefine.Def_ChannelChat_Area:
#        return
#    sendPack = ChPyNetSendPack.tagGCVoiceChat()
#    sendPack.Clear()
#    sendPack.ChannelType = clientPack.ChannelType
#    sendPack.SrcName = curPlayer.GetName()
#    sendPack.SrcNameLen = len(curPlayer.GetName())
#    sendPack.PlayerID = curPlayer.GetID()
#    sendPack.Len = clientPack.Len
#    sendPack.Content = clientPack.Content
#    sendPack.Extras = GetTalkExtraValue(curPlayer)
#    sendPack.ExtraValue = len(sendPack.Extras)
#
#    # 区域频道
#
#    #如果在普通地图, 就广播, 如果在副本就单个通知
#    if GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtNull:
#        curPlayer.BroadCastAll(sendPack.GetBuffer(), len(sendPack.GetBuffer()))
#    else:
#        playerManager = GameWorld.GetMapCopyPlayerManager()
#
#        for index in range(0 , playerManager.GetPlayerCount()):
#            #广播玩家
#            tempPlayer = playerManager.GetPlayerByIndex(index)
#            if not tempPlayer.GetPlayerID():
#                continue
#
#            if PlayerTJG.GetIsTJG(tempPlayer):
#                continue
#
#            NetPackCommon.SendFakePack(tempPlayer, sendPack)
    return