ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -29,7 +29,6 @@
import FunctionNPCCommon
import PlayerGMOper
import ReadChConfig
import PetControl
import OperControlManager
import ShareDefine
import NetPackCommon
@@ -39,86 +38,61 @@
import PlayerLVAward
import PlayerGoldGift
import PlayerSignDay
import PlayerPet
import PlayerPrestigeSys
import PlayerFamily
import PlayerLoginDayAward
import PlayerGodWeapon
import PlayerGoldInvest
import PlayerActivity
import FBCommon
import PlayerWishingWell
import PlayerSuccess
import PlayerDienstgrad
import PlayerFreeGoods
import PlayerCrossRealmPK
import PlayerCrossChampionship
import GameFuncComm
import PlayerBossReborn
import PlayerWeekParty
import PlayerFeastWeekParty
import PlayerFeastTravel
import PlayerFamilyTaofa
import PlayerFeastLogin
import PlayerFeastWish
import PlayerActLogin
import PlayerTreasure
import PlayerRune
import PlayerFamilyRedPacket
import IpyGameDataPY
import EventReport
import OpenServerCampaign
import PassiveBuffEffMng
import PlayerFlashSale
import PlayerFlashGiftbag
import PlayerDailyGiftbag
import PlayerCostRebate
import PlayerActBuyOne
import PlayerActGrowupBuy
import PlayerActCollectWords
import PlayerActTotalRecharge
import PlayerActRechargePrize
import PlayerActLianqi
import PlayerActGodGift
import PlayerActFamilyCTGAssist
import PlayerActRechargeRebateGold
import PlayerActManyDayRecharge
import PlayerActSingleRecharge
import PlayerSpringSale
import GY_Query_BossFirstKill
import PlayerCrossYaomoBoss
import PlayerFeastRedPacket
import PlayerLuckyCloudBuy
import PlayerLuckyTreasure
import Item_ResetAttrPoint
import CrossActCTGBillboard
import CrossActAllRecharge
import PlayerFuncSysPrivilege
import PlayerActTurntable
import PlayerTongTianLing
import CrossRealmPlayer
import OpenServerActivity
import ChNetSendPack
import PlayerArena
import PyGameData
import PlayerCoin
import PlayerCharm
import PlayerDogz
import PlayerCoat
import PlayerFB
import PlayerFaQi
import SkillShell
import PlayerGubao
import PlayerShentong
import PlayerCustomAward
import PlayerZhanling
import PlayerTree
import PlayerLLMJ
import PlayerLianTi
import PlayerTask
import PlayerYinji
import PlayerLove
import GameObj
import PlayerChangeJob
import PlayerFace
import PlayerChatBox
import PlayerXiangong
import PlayerGoldRush
import PlayerActLoginNew
@@ -129,16 +103,29 @@
import PlayerActTask
import PlayerMail
import DBDataMgr
import PlayerViewCache
import UpdatePlayerName
import GameServerRefresh
import IPY_ServerDefine
import IPY_PlayerDefine
import CommFunc
from PyMongoDB import RecvPackToMapDB
import GMT_BroadCast
import PyMongoMain
import PlayerTalk
import PlayerHero
import PlayerPreset
import PlayerOnline
import PlayerBeauty
import PlayerTravel
import PlayerMingge
import TurnAttack
import ObjPool
import PlayerHJG
import DBFamily
import CrossPlayer
import CrossMsg
import CrossMgr
import ChEquip
import datetime
import time
@@ -177,10 +164,6 @@
    if FBLogic.PlayerLoginInFBCheck(curPlayer, tick):
        #玩家是第一次登录, 并且玩家需要踢回原来地图
        return
    #刷新人物日期状态
    #GameWorld.Log('PlayerEventCounter.UpdatePlayerLoginTime')
    PlayerEventCounter.UpdatePlayerLoginTime(curPlayer)
    return
#// A1 20 货币兑换 #tagCMMoneyExchange
@@ -253,11 +236,6 @@
    __Sync_ClientBuff(curPlayer)
    
    PlayerState.Sync_PKBossState(curPlayer)
    if PlayerControl.GetCrossMapID(curPlayer):
        CrossRealmPlayer.DoExitCrossRealm(curPlayer)
    PetControl.DoLogic_PetLoadMapOK(curPlayer)
    
    # 恢复视野,刷新自己的视野
    curPlayer.SetVisible(True)
@@ -411,17 +389,22 @@
def DoPlayerLogin(curPlayer, tick):
    #这里只做初始化逻辑
    curPlayer.SetDict(ChConfig.Def_PlayerKey_LoadMapIsLogin, 1)
    CrossPlayer.GetCrossPlayerMgr().RegistPlayer(curPlayer.GetPlayerID())
    
    #通知时间
    Sync_PyServerDataTimeToClient(curPlayer)
    Sync_OpenServerDay(curPlayer)
    #通知玩家基本信息
    curPlayer.Sync_ClientPlayerLogin()  #01 02 玩家初始化#tagCDBPlayer
    SyncSettingData(curPlayer)
    
    # 屏蔽跨服下关闭和子服重复的数据的发送 pushsend接口, notifyall正常发送
    # !!!必要发送的数据要注意位置
    if GameWorld.IsCrossServer():
        curPlayer.SetForbiddenSyncClientState(True)
    # !!!先处理检查OnDay,再处理玩家登录的功能数据,防止某些功能login处理数据后又被onday重置
    PlayerEventCounter.UpdatePlayerLoginTime(curPlayer)
    
    __DoPlayerLoginServer(curPlayer, tick)
    
@@ -452,8 +435,6 @@
        
        DataRecordPack.DR_PlayerLogin(curPlayer)
        EventReport.WriteEvent_login(curPlayer)
        #---玩家上线, 宠物逻辑处理---
        #PetControl.DoLogic_PetInfo_OnLogin(curPlayer, tick)
        return
    
    leaveServerSecond = PlayerControl.GetPlayerLeaveServerSecond(curPlayer)
@@ -473,9 +454,7 @@
    SyncGuideState(curPlayer)
    
    #上线检查一次装备属性
    ItemControler.OnPlayerLogin(curPlayer)
    #更新服务器组ID
    PlayerControl.UpdPlayerServerGroupID(curPlayer)
    ItemControler.OnPlayerLogin(curPlayer)
    
    #上线学习技能
    #SkillCommon.PlayerLoginCheckLearnSkill(curPlayer)
@@ -497,27 +476,19 @@
    PlayerControl.SyncOnLineTimeTotal(curPlayer)
    #PlayerControl.SyncOnLineTimeLastOpenPack(curPlayer, IPY_GameWorld.rptItem)
    PlayerControl.SyncTrainRealmLV(curPlayer)
    PlayerGodWeapon.OnLogin(curPlayer)
    PlayerPrestigeSys.OnLogin(curPlayer)
    #DataRecordPack.DR_PlayerLogin(curPlayer)
    EventReport.WriteEvent_login(curPlayer)
    
    # 合服首登处理
    __DoMixServerFirstLogin(curPlayer)
    #__DoMixServerFirstLogin(curPlayer)
    PlayerBillboard.BillboardOnLogin(curPlayer)
    
    #玩家扩展信息
    __SyncPlayerInfoEx(curPlayer)
    
    #补丁包下载奖励
    GiveDownloadPatchAward(curPlayer)
    #PKģʽ
    #SyncPKModel(curPlayer)
    #---玩家上线, 宠物逻辑处理---
    #PetControl.DoLogic_PetInfo_OnLogin(curPlayer, tick)
    #PlayerPet.OnPlayerPetLogin(curPlayer)
    
    # 通知等级奖励领取记录
    PlayerLVAward.Sync_LVAwardGetRecordInfo(curPlayer)
@@ -549,15 +520,6 @@
    # 通知累计登陆礼
    PlayerLoginDayAward.OnLoginNotifyLoginDayAward(curPlayer)
    
    # 开服活动奖励信息
    OpenServerCampaign.OnOpenServerCampaignLogin(curPlayer)
    # 采集NPC次数通知
    #NPCCommon.SyncCollNPCTime(curPlayer)
    # 每日活跃度
    PlayerActivity.OnLogin(curPlayer)
    # 副本进入时间
    FBCommon.FBOnLogin(curPlayer)
    
@@ -576,22 +538,6 @@
    #同步自动战斗配置记录
#    Sync_AutoFightSetting(curPlayer)
    
    PlayerFamily.OnPlayerLogin(curPlayer, tick)
    #改到 GameServerRefresh GameSever_PlayerInitOK后处理才能保证玩家已经在Gameserver注册
    #PlayerDienstgrad.RefreshBillBoardDienstgrad(curPlayer)
    # 称号
    PlayerDienstgrad.Sync_AllDienstgradOnLogin(curPlayer)
    # ʱװ
    PlayerCoat.OnLogin_Coat(curPlayer)
    # 跨服PK
    PlayerCrossRealmPK.DoPlayerLogin(curPlayer)
    PlayerCrossChampionship.DoPlayerLogin(curPlayer)
    # 幸运云购
    PlayerLuckyCloudBuy.OnPlayerLogin(curPlayer)
    # 竞技场
    PlayerArena.OnLogin(curPlayer)
    
@@ -600,19 +546,8 @@
    PlayerControl.NotifyUseMoneyTotal(curPlayer)
    #通知基础属性
    #NotifyPlayerBasePoint(curPlayer)
    #跨服充值排行
    CrossActCTGBillboard.OnPlayerLogin(curPlayer)
    #跨服全民充值
    CrossActAllRecharge.OnPlayerLogin(curPlayer)
    #消费返利
    PlayerCostRebate.OnPlayerLogin(curPlayer)
    #累计充值
    PlayerActTotalRecharge.OnPlayerLogin(curPlayer)
    #累计充值返利仙玉
    PlayerActRechargeRebateGold.OnPlayerLogin(curPlayer)
    #充值返利
    PlayerActRechargePrize.OnPlayerLogin(curPlayer)
    #成长必买
    PlayerActGrowupBuy.OnPlayerLogin(curPlayer)
    #限时特惠
@@ -630,39 +565,24 @@
    #集字活动
    PlayerActCollectWords.OnPlayerLogin(curPlayer)
    ChItem.Sync_ItemDayUseCnt(curPlayer)
    # 符印登录通知
    PlayerRune.PlayerRuneLogin(curPlayer)
    # 仙盟红包登录通知
    PlayerFamilyRedPacket.OnPlayerLogin(curPlayer)
    PlayerFeastRedPacket.DoPlayerOnLogin(curPlayer)
    # 商店物品购买次数登录通知
    FunctionNPCCommon.ShopItemOnLogin(curPlayer)
    # 通知设置的被动功法
    #PassiveBuffEffMng.OnLoginGFPassive(curPlayer)
    # 极品白拿
    PlayerFreeGoods.OnLogin(curPlayer)
    # BOSS复活活动
    PlayerBossReborn.OnLogin(curPlayer)
    # 周狂欢活动
    PlayerWeekParty.OnLogin(curPlayer)
    # 购买次数礼包活动
    PlayerActBuyCountGift.OnPlayerLogin(curPlayer)
    # 任务活动
    PlayerActTask.OnPlayerLogin(curPlayer)
    # 运势活动
    PlayerActYunshi.OnPlayerLogin(curPlayer)
    # 轮回殿活动
    PlayerActLunhuidian.OnPlayerLogin(curPlayer)
    # 登录活动
    PlayerActLoginNew.OnPlayerLogin(curPlayer)
    # 节日巡礼活动
    PlayerFeastWeekParty.OnLogin(curPlayer)
    # 节日登录活动
    PlayerFeastLogin.OnPlayerLogin(curPlayer)
    # 节日祝福活动
    PlayerFeastWish.OnPlayerLogin(curPlayer)
    # 节日游历活动
    PlayerFeastTravel.OnPlayerLogin(curPlayer)
    # 登录奖励活动
    PlayerActLogin.OnLogin(curPlayer)
    # 炼器活动
@@ -690,10 +610,6 @@
    PlayerFB.OnLogin(curPlayer)
    #技能专精信息
    #SkillShell.NotifyElementSkillInfo(curPlayer)
    #Boss首杀
    GY_Query_BossFirstKill.OnPlayerLogin(curPlayer)
    #通天令
    PlayerTongTianLing.OnPlayerLogin(curPlayer)
    #创角奖励
    Sync_CreateRoleAwardInfo(curPlayer)
    #自定义奖励
@@ -728,7 +644,7 @@
    curPlayer.SetState(0)   # 脱机挂恢复为正常上线
    curPlayer.SetCountryLastWeekHornor(0) # 通知数据库是否保存还是下线,做一次恢复,1为保存 0为正常下线
    
    PlayerControl.DoGMForbidenTalkOnLogin(curPlayer)
    PlayerControl.OnPlayerLogin(curPlayer)
    DataRecordPack.DR_PlayerLogin(curPlayer) # 放最后,记录等级、经验等信息
    return
@@ -744,13 +660,13 @@
    
    else:
        PyMongoMain.GetUserCtrlDB().OnPlayerLogin(curPlayer)
        GMT_BroadCast.OnPlayerLogin(curPlayer)
        PlayerFamily.OnPlayerLogin(curPlayer, tick)
        PlayerHero.OnPlayerLogin(curPlayer)
        PlayerMail.OnPlayerLogin(curPlayer)
        PlayerChatBox.OnPlayerLogin(curPlayer)
        PlayerFace.OnPlayerLogin(curPlayer)
        PlayerHJG.OnPlayerLogin(curPlayer)
        PlayerXiangong.OnPlayerLogin(curPlayer)
        PlayerGubao.OnPlayerLogin(curPlayer)
        PlayerShentong.OnPlayerLogin(curPlayer)
        PlayerZhanling.OnPlayerLogin(curPlayer)
        PlayerTask.OnPlayerLogin(curPlayer)
        PlayerTree.OnPlayerLogin(curPlayer)
@@ -758,14 +674,237 @@
        PlayerActFamilyGCZ.OnPlayerLogin(curPlayer)
        PlayerTalk.OnPlayerLogin(curPlayer)
        SyncADCntInfo(curPlayer)
        UpdatePlayerName.OnPlayerLogin(curPlayer)
        PlayerActivity.OnPlayerLogin(curPlayer)
        PlayerLLMJ.OnPlayerLogin(curPlayer)
        PlayerBeauty.OnPlayerLogin(curPlayer)
        PlayerTravel.OnPlayerLogin(curPlayer)
        PlayerMingge.OnPlayerLogin(curPlayer)
        OpenServerActivity.OnPlayerLogin(curPlayer)
        PlayerPreset.OnPlayerLogin(curPlayer)
        CrossPlayer.OnPlayerLogin(curPlayer)
        PlayerActLunhuidian.OnPlayerLogin(curPlayer)
        
        __OnFixVersion(curPlayer) # 修正线上玩家数据用,暂时放最后
        # 上线查询一次充值订单
        curPlayer.SendDBQueryRecharge()
        # curPlayer.SendDBQueryRecharge() 不查了,由在线轮询触发即可
        SyncOnlineStateToCross(curPlayer, 1)
        
    # 通知GameServer地图最终登录成功了
    isMixServerFirstLogin = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MixServerFirstLogin)
    msg = str([isMixServerFirstLogin])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "PlayerRealLoginOK", msg, len(msg))
    return
#def C2S_PlayerLoginOK(playerID):
#    ## 跨服登录成功后续处理
#    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
#    if not curPlayer:
#        return
#
#    PlayerFamily.CrossServer_PlayerLogin(curPlayer)
#    return
def __OnFixVersion(curPlayer):
    ''' 修正线上玩家数据内容
    每次有需要修正时,只要定义一个新的系统内容版本号  sysFixVersion , 然后玩家根据自身版本号进行逐步修正即可
    这样只用到一个key即可,不需要每次都定义新的key
    '''
    playerID = curPlayer.GetPlayerID()
    sysFixVersion = 2025123012 # 系统定义的最后一次修正版本号,一般以 yyyyMMddhh 定义为版本号
    playerVersion = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FixVersion)
    if not playerVersion:
        createRoleTime = curPlayer.GetCreateRoleTime() # 按创角
        ymd = createRoleTime.split(" ")[0]
        playerVersion = GameWorld.ToIntDef("%s00" % ymd.replace("-", ""))
        GameWorld.DebugLog("默认数据版本为创角日期: %s, %s" % (createRoleTime, playerVersion), playerID)
    if playerVersion == sysFixVersion:
        GameWorld.DebugLog("玩家当前数据版本号已是最新版本! playerVersion=%s" % (playerVersion), playerID)
        return
    GameWorld.Log("玩家当前数据版本号不等于系统版本号,开始修正! playerVersion=%s != %s" % (playerVersion, sysFixVersion), playerID)
    # 修正玩家装备生命数值: 策划调整了生命占比,同步修改了生命战力,故需修正线上玩家装备生命,防止战力下降
    fixVersion = 2025123012
    if playerVersion < fixVersion:
        ChEquip.FixRoleEquipHP(curPlayer, fixVersion)
        # 每个版本修正完需要立即更新到对应的版本号值,防止中间某个版本修正失败,导致重登后重复修正已经处理的版本
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FixVersion, fixVersion)
    # 其他
    # 需要按修正版本时间顺序依次处理!!!需要按修正版本时间顺序依次处理!!!需要按修正版本时间顺序依次处理!!!
    # 最终强制设置为最新版本号
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FixVersion, sysFixVersion)
    return
def GetSyncCrossServerIDAndFuncInfo():
    ## 获取需要同步给的目标跨服服务器ID及相关额外的功能信息
    dataEx = {}
    serverIDList = []
    # 公会
    if DBFamily.IsFamilyCross():
        crossFamilyServerID = DBDataMgr.GetFamilyMgr().GetCurCrossServerID()
        if crossFamilyServerID > 0:
            dataEx["crossFamilyServerID"] = crossFamilyServerID
            if crossFamilyServerID not in serverIDList:
                serverIDList.append(crossFamilyServerID)
    # 其他跨服功能
    return serverIDList, dataEx
def OnPlayerBaseInfoChange(curPlayer, refreshType=0):
    '''玩家基础信息变更同步更新其他功能,可以视为同步到以前的GameServer
    除了相关基础值变化同步外,上下线状态变更也会附带基础信息的同步
    '''
    playerID = curPlayer.GetPlayerID()
    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
    crossPlayer = crossPlayerMgr.FindCrossPlayer(playerID)
    if not crossPlayer:
        return
    # 公会成员
    PlayerFamily.RefreshFamilyMember(crossPlayer)
    # 相关排行榜
    if refreshType == IPY_PlayerDefine.CDBPlayerRefresh_PlayerName:
        PlayerBillboard.UpdatePlayerBillboardName(curPlayer)
    # 社交名待更新
    # --------------------------------------------------------------
    syncCD = 2000
    if refreshType == IPY_PlayerDefine.CDBPlayerRefresh_FightPower:
        syncCD = 60 * 1000
    # 同步给相关跨服
    tick = GameWorld.GetGameWorld().GetTick()
    lastSyncTick = curPlayer.GetDictByKey("S2C_PlayerBaseInfo")
    if lastSyncTick and (tick - lastSyncTick) <= syncCD:
        # 短时间内只同步一次
        #GameWorld.DebugLog("同步基础属性CD中! refreshType=%s,syncCD=%s,pass=%s" % (refreshType, syncCD, tick - lastSyncTick))
        return
    curPlayer.SetDict("S2C_PlayerBaseInfo", tick)
    if refreshType == IPY_PlayerDefine.CDBPlayerRefresh_LV:
        if curPlayer.GetLV() < 20:
            return
    serverIDList = GetSyncCrossServerIDAndFuncInfo()[0]
    if not serverIDList:
        return
    playerID = curPlayer.GetPlayerID()
    baseInfo = PlayerViewCache.GetPlayerBaseViewInfo(playerID, curPlayer)
    dataMsg = {"baseInfo":baseInfo}
    CrossMsg.SendToCrossServer(ShareDefine.S2C_PlayerBaseInfo, dataMsg, serverIDList, playerID)
    return
def S2C_PlayerBaseInfo(dataMsg, fromServerID, playerID):
    isOnline = True
    baseInfo = dataMsg["baseInfo"]
    UpdCrossPlayerFromMainServer(fromServerID, playerID, baseInfo, isOnline)
    return
def UpdCrossPlayerFromMainServer(fromServerID, playerID, baseInfo, isOnline):
    ## 更新CrossPlayer根据游戏服同步的信息
    # @return: crossPlayer
    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
    crossPlayer = crossPlayerMgr.FindCrossPlayer(playerID)
    if not crossPlayer:
        crossPlayer = crossPlayerMgr.RegistPlayer(playerID) # 跨服不存在该玩家信息,直接注册,不用管是否在线
    # 信息更新
    curCache = PlayerViewCache.UpdPlayerBaseViewInfo(playerID, baseInfo, not isOnline)
    crossPlayer.UpdByViewCache(curCache, fromServerID)
    # 公会成员更新
    PlayerFamily.RefreshFamilyMember(crossPlayer)
    # 如果是离线的处理
    if not isOnline:
        PlayerViewCache.OnCrossPlayerLogout(crossPlayer)
        crossPlayerMgr.DeletePlayer(playerID)
    return crossPlayer
def SyncOnlinePlayerToCross(toCrossServerID):
    ## 重新同步在线玩家,确保目标服务器有跨服玩家基础数据,一般用于重连跨服、或某些跨服功能开启时重新同步确保目标服务器有本服在线玩家基本数据信息
    playerManager = GameWorld.GetPlayerManager()
    for i in xrange(playerManager.OnlineCount()):
        curPlayer = playerManager.OnlineAt(i)
        if not GameWorld.IsNormalPlayer(curPlayer):
            continue
        SyncOnlineStateToCross(curPlayer, 1, False, toCrossServerID)
    return
def SyncOnlineStateToCross(curPlayer, isOnline, isLoginout=True, toCrossServerID=0):
    ## 同步玩家在线状态给相关跨服
    # @param isLoginout: 是否上下线的,重新连上跨服时也会重新同步
    playerID = curPlayer.GetPlayerID()
    # 游戏服、跨服通用,当做以前GameServer的Player处理
    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
    # 离线直接清除
    if not isOnline:
        crossPlayerMgr.DeletePlayer(playerID)
    serverIDList, dataEx = GetSyncCrossServerIDAndFuncInfo()
    if not serverIDList:
        # 没有需要同步的跨服不处理
        return
    if toCrossServerID:
        if toCrossServerID not in serverIDList:
            return
        serverIDList = [toCrossServerID] # 如果有指定,指同步给该服
    baseInfo = PlayerViewCache.GetPlayerBaseViewInfo(playerID, curPlayer)
    dataMsg = {"isOnline":isOnline, "isLoginout":isLoginout, "baseInfo":baseInfo}
    dataMsg.update(dataEx)
    CrossMsg.SendToCrossServer(ShareDefine.S2C_OnlineState, dataMsg, serverIDList, playerID)
    return
def S2C_OnlineState(dataMsg, fromServerID, playerID):
    '''收到游戏服玩家在线状态同步
    跨服收到在线状态同步时都视为在跨服上线,需要处理跨服在线/上线的逻辑
    不然在跨服维护游戏服不维护的情况下,等跨服重开后,游戏服重新同步在线玩家,此时如果跨服不处理登录逻辑,会少同步封包
    如公会,跨服维护之后登录的玩家会取不到公会数据,等跨服重开后,需视为登录重新同步
    与跨服重连一样的道理,都是重新同步所有信息
    '''
    isOnline = dataMsg["isOnline"]
    #isLoginout = dataMsg["isLoginout"] # 如果个别跨服功能有需要对真实上下线做特殊处理的可使用该参数判断
    baseInfo = dataMsg["baseInfo"]
    crossPlayer = UpdCrossPlayerFromMainServer(fromServerID, playerID, baseInfo, isOnline)
    # 其他跨服功能处理,暂时仅上下线时处理
    curServerID = GameWorld.GetGameWorld().GetServerID()
    #if isLoginout:
    # 公会
    if "crossFamilyServerID" in dataMsg:
        crossFamilyServerID = dataMsg["crossFamilyServerID"]
        if curServerID == crossFamilyServerID:
            if isOnline:
                PlayerFamily.OnCrossPlayerLogin(crossPlayer)
            else:
                PlayerFamily.OnCrossPlayerLogout(crossPlayer)
    # 最后处理缓存,先放在更新中处理删除,有问题再放后面
    #if not isOnline:
    #    PlayerViewCache.OnCrossPlayerLogout(crossPlayer)
    #    CrossPlayer.GetCrossPlayerMgr().DeletePlayer(playerID)
    # 最后同步处理跨服登录成功
    #if isLoginout and isOnline:
    #    CrossMsg.SendToClientServer(ShareDefine.C2S_PlayerLoginOK, {}, [fromServerID], playerID)
    return
## 玩家扩展信息同步
@@ -791,8 +930,7 @@
    # 特殊说明: 如果地图没有完全初始化好,客户端断开或者异常等情况会触发RunGateGameServerMapServerKickOutPlayerNoSave
    # 那么在DoPlayerLogin 中设置的数据将不会被保存, 如会导致第一个任务重复触发问题,记录多次发送
    EventReport.WriteEvent_Entry(curPlayer, 4)
    #EventReport.EventReport(ShareDefine.Def_UserAction_FirstLogin, "", curPlayer)
    curPlayer.SetFightPoint(1) # 初始化为1倍消耗
    
    #---补满血满魔---
@@ -856,9 +994,6 @@
    
    # 重置首充双倍
    PlayerCoin.DoResetCTGCount(curPlayer, "MixServer")
    # 重置商店购买次数,暂定只重置类型 7 的
    FunctionNPCCommon.ResetShopItemBuyCount(curPlayer, [7])
    
    # 合服邮件,盟主专属邮件在GameServer处理
    mailItemList = IpyGameDataPY.GetFuncEvalCfg("MixServerMail", 1)
@@ -1051,10 +1186,6 @@
    
    #检查更新总战斗力
    #PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer, True)
    EventReport.WriteEvent_FightPower(curPlayer)
    #清除在本地图离线记录信息
    PlayerControl.RemoveLeaveServerPlayerInfo(curPlayer.GetPlayerID())
    
    PyGameData.g_needRefreshMapServerState = True # 有玩家登录地图时设置需要刷新
    return
@@ -1124,7 +1255,8 @@
        #到此处已经可以保存数据,即使客户端不回包断线
        #原 //01 07 地图读取OK#tagCInitMapOK 逻辑 直接调用
        __Func_LoadMapOK(index, tick)
        GameServerRefresh.GameSever_PlayerInitOK(index, tick)
        DoPlayerRealLoginOK(curPlayer, tick)
        #GameServerRefresh.GameSever_PlayerInitOK(index, tick) GameServer已废弃,不再执行该逻辑
    except:
        curPlayer.Kick(IPY_GameWorld.disWaitForPlayerLoinError)
        import traceback
@@ -1193,9 +1325,6 @@
    #    GameObj.SetHPFull(curSummon)
    #===========================================================================
    
    #初始化宠物 通知客户端
    PetControl.Sync_PetInfo_ChangeMap(curPlayer, tick)
    #通知GameServer自己现在的地图
    #curPlayer.Sync_GameServer_MapID()
    
@@ -1231,6 +1360,10 @@
    
    #初始化英雄背包
    PlayerControl.Init_PackCount(curPlayer, ShareDefine.rptHero)
    #初始化卦玉背包
    PlayerControl.Init_PackCount(curPlayer, ShareDefine.rptMGGuayu, defaultMax=True, isSync=False)
    PlayerControl.Init_PackCount(curPlayer, ShareDefine.rptMGTuiyan, defaultMax=True, isSync=False)
    
    #初始化临时交换背包,默认最大个数
    PlayerControl.Init_PackCount(curPlayer, ShareDefine.rptTempSwap, defaultMax=True, isSync=False)
@@ -1393,30 +1526,6 @@
    #if curPlayer.GetPlayerAction() != IPY_GameWorld.paEvent:
    curPlayer.SetCanMove(True)
    
    #同步客户端tick
    #这个封包要在EndLoadMap, 上马之前发, 否则客户端处理时机不对(客户端封包缓存机制)
    #curPlayer.Sync_ClientTick()
    #做上一个地图的上马/骠车逻辑
    #恢复自己的状态
    playerVehicle = curPlayer.GetLastMapPlayerVehicle()
    if playerVehicle == IPY_GameWorld.pvHorse:
        #玩家在骑马中
        if not PlayerHorse.PlayerRideHorseUp(curPlayer, False, False):
        #=======================================================================
        #    playerHorseState = curPlayer.GetLastMapPlayerRidehorseState()
        #    if playerHorseState != IPY_GameWorld.prsNormal:
        #        #切换地图, 恢复急行状态
        #        curPlayer.SetPlayerRidehorseState(playerHorseState)
        #
        #    #刷新人物属性 所有状态
        #    playerControl = PlayerControl.PlayerControl(curPlayer)
        #    playerControl.RefreshAllState()
        # else:
        #=======================================================================
            #此时已经是下马状态不需要刷状态 但是需要通知客户端下马
            PlayerHorse.PlayerRideHorseDown(curPlayer, False)
    #激活玩家(保证持续性Buff处理间隔)
    PlayerControl.SetIsNeedProcess(curPlayer, True)
@@ -1425,9 +1534,6 @@
    
    #如果登录的副本,执行进入副本逻辑, 因为有时间响应, 必须在EndLoadMap之后...
    FBLogic.DoEnterFBLogic(curPlayer, tick)
    #触发切换地图宠物逻辑
    PetControl.DoLogic_PetLoadMapOK(curPlayer)
    #---检查是否卡障碍---
    curMap = GameWorld.GetMap()
@@ -1464,9 +1570,6 @@
    #申请得到奖励物品
    #curPlayer.DataServer_CheckPrizeItem()
    #防止玩家读取地图时未触发OnDay,读取地图后再次验证(2009.9.11)
    PlayerEventCounter.UpdatePlayerLoginTime(curPlayer)
    
    #设置阵营
    if curPlayer.GetFaction() != ChConfig.CampType_Neutral \
@@ -1631,7 +1734,7 @@
            return
        ItemCommon.ReduceItem(curPlayer, itemPack, [delIndex], 1, False, ChConfig.ItemDel_ResetAttrPoint)
    
    Item_ResetAttrPoint.DoResetAttrPoint(curPlayer, 0, 0, 0)
    #Item_ResetAttrPoint.DoResetAttrPoint(curPlayer, 0, 0, 0)
    return
def NotifyPlayerBasePoint(curPlayer, syncAttrIDList=[]):
@@ -1765,9 +1868,9 @@
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    
    #防外挂 不可移动
    if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
                                      == ChConfig.Def_AutoCheck_State_Danger:
        return
    #if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
    #                                  == ChConfig.Def_AutoCheck_State_Danger:
    #    return
    
    
    #不可移动行为状态, 判断客户端限制
@@ -1829,20 +1932,6 @@
    
    curPlayer.ChangePos(sendPack_DestX, sendPack_DestY)
    #curPlayer.SetClientMoveTick(sendPack_WorldTick)
    fightPet = curPlayer.GetPetMgr().GetFightPet()
    #无出战宠物
    if fightPet == None:
        return
    if GameWorld.GetDist(fightPet.GetPosX(), fightPet.GetPosY(), sendPack_DestX, sendPack_DestY) <= 4:
        #战斗中不频繁移动
        return
    #出战宠物同时移动
    PetControl.FightPetFollowMove(curPlayer, sendPack_StartX, sendPack_StartY)
    return
#---------------------------------------------------------------------
@@ -1916,9 +2005,6 @@
    # 在UpdatePos 调用间隔内多次调用move会使 m_StartMoveTick 重置,导致无法移动
    # 而在 CheckMovePos -> PlayerRefreshPos -> __FixPlayerPos -> ChangePos 造成移动的现象
    curPlayer.Move(client_DestX, client_DestY)
    #出战宠物同时移动
    #PetControl.FightPetFollowMove(curPlayer, client_DestX, client_DestY, client_StartX, client_StartY)
    return
##移动点检查, checkObj 是移动对象(在人镖合一状态下, 输入为骠车
@@ -2134,29 +2220,16 @@
    #流向记录玩家下线
    DataRecordPack.DR_PlayerDisconnect(curPlayer)
    
    #玩家未回图形验证码下线将会记录错误次数
    #===========================================================================
    # if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_Captcha_WaitSign) \
    # == PlayerAutoCheckOnline.Def_Captcha_WaitAnswer:
    #    PlayerAutoCheckOnline.CaptchaAnswerErr(curPlayer, tick, False)
    #
    #    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_Captcha_WaitSign, PlayerAutoCheckOnline.Def_Captcha_Safe)
    #
    #===========================================================================
    #@warning: 等字段统一修改,删除双倍经验BUFF
    #PlayerDoubleExpSys.DeleteDoubleExpBuff(curPlayer, ChConfig.Def_DoubleExpNote_StopOff)
    #设置RouteServerInitOK字典
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RouteServerInitOK, 0)
    
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PlayerKey_CrossRegisterMap, 0)
    
    #下线召回宠物
    PetControl.ReCallFightPet(curPlayer)
    #离线session
    EventReport.WriteEvent_session(curPlayer)
    
    #最后同步跨服服务器
    SyncOnlineStateToCross(curPlayer, 0)
    #需放最后
    PlayerOnline.OnPlayerLogoff(curPlayer)
    return
@@ -2193,6 +2266,76 @@
        return
    
    curPlayer.SetSetting(setting)
    return
#// A1 31 前端自定义保存设置内容 #tagCSSettingData
#
#struct tagCSSettingData
#{
#    tagHead        Head;
#    BYTE        KeyNum;        // 自定义key编号,后端使用数字key存储,前端自行进行转换定义,限制100个
#    BYTE        DataLen;
#    char        SetData[DataLen];    //自定义保存的内容
#};
def OnSettingData(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    keyNum = clientData.KeyNum
    setData = clientData.SetData
    setData = setData.replace(" ", "") # 去空格
    keyStr = str(keyNum)
    gameRecMgr = DBDataMgr.GetGameRecMgr()
    preSetRecMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_Setting, playerID)
    recData = preSetRecMgr.GetOneRecData(True)
    if not recData:
        return
    dataDict = recData.GetUserDict()
    if not setData:
        dataDict.pop(keyStr, None)
    else:
        keyMax = 100
        if keyStr not in dataDict:
            if len(dataDict) >= keyMax:
                GameWorld.ErrLog("存储个数达到上限! keyMax=%s" % keyMax)
                return
        dataDict[keyStr] = setData
    SyncSettingData(curPlayer, keyStr)
    return
def SyncSettingData(curPlayer, keyStr=""):
    playerID = curPlayer.GetPlayerID()
    gameRecMgr = DBDataMgr.GetGameRecMgr()
    preSetRecMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_Setting, playerID)
    recData = preSetRecMgr.GetOneRecData()
    if not recData:
        return
    dataDict = recData.GetUserDict()
    settingDataList = []
    syncKeyList = [keyStr] if keyStr else dataDict.keys()
    for keyStr in syncKeyList:
        if keyStr in dataDict:
            setData = dataDict[keyStr]
        else:
            setData = ""
        keyNum = GameWorld.ToIntDef(keyStr, None)
        if keyNum == None:
            continue
        sData = ChPyNetSendPack.tagSCSettingData()
        sData.KeyNum = keyNum
        sData.SetData = setData
        sData.DataLen = len(sData.SetData)
        settingDataList.append(sData)
    if not settingDataList:
        return
    clientPack = ChPyNetSendPack.tagSCSettingDataInfo()
    clientPack.SettingDataList = settingDataList
    clientPack.DataCnt = len(clientPack.SettingDataList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
#// A2 29 设置小助手 #tagCMSetLittleHelper
@@ -2803,8 +2946,6 @@
    elif rebornType == ChConfig.rebornType_MainCity:
        #直接取db中配置的复活点
        PlayerControl.PlayerResetWorldPos(curPlayer, gameMap.GetRebornMapID(), gameMap.GetRebornMapX(), gameMap.GetRebornMapY())
    #重新召唤宠物
    PlayerPet.AutoSummonPet(curPlayer)
    
    #复活成功,重置状态
    PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paNull)
@@ -2864,8 +3005,7 @@
#    WORD        LineID;
#};
def OnEnterCrossServer(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    PlayerControl.PlayerEnterCrossServer(curPlayer, clientData.DataMapID, clientData.LineID)
    #curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    return
    
#===============================================================================
@@ -3178,54 +3318,6 @@
    curPlayer.Syn_OfflineTimeQueryResult() # 通知客服端离线时间
    return
#//B0 24 领取家族悬赏奖励 #tagReceiveFamilyArrestAward
#
#struct    tagReceiveFamilyArrestAward
#
#{
#    tagHead        Head;
#    DWORD        ArrestID;        //悬赏任务ID
#};
## 领取家族悬赏奖励
#  @param index: 玩家索引
#  @param clientData: 封包结构体
#  @param tick: 时间戳
#  @return: None
def ReceiveFamilyArrestAward(index, clientData, tick):
    return
#//B0 26 请求家族悬赏奖励领取情况 #tagQueryFamilyArrestAwardReceiveState
#
#struct    tagQueryFamilyArrestAwardReceiveState
#
#{
#    tagHead        Head;
#};
## 请求家族悬赏奖励领取情况
#  @param index: 玩家索引
#  @param clientData: 封包结构体
#  @param tick: 时间戳
#  @return: None
def QueryFamilyArrestAwardReceiveState(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    Sync_FamilyArrestAwardReceiveState(curPlayer)
    return
## 通知客户端家族悬赏任务奖励领取情况
#  @param curPlayer: 玩家实例
#  @return: None
def Sync_FamilyArrestAwardReceiveState(curPlayer):
    awardReceiveState = ChPyNetSendPack.tagFamilyArrestAwardReceiveState()
    awardReceiveState.Clear()
    state = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyArrestAwardState)
    awardReceiveState.ReceiveState = state
    NetPackCommon.SendFakePack(curPlayer, awardReceiveState)
    return
def PlayerOnDay(curPlayer):
    #玩法前瞻奖励
    gameNoticeAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GameNoticeAwardState)
@@ -3274,21 +3366,47 @@
    # 活跃度奖励
    if rewardType == ChConfig.Def_RewardType_Activity:
        PlayerActivity.GetActivityAward(curPlayer, dataEx)
    # 活跃放置奖励
    elif rewardType == ChConfig.Def_RewardType_ActivityPlace:
        PlayerActivity.GetActivityPlaceReward(curPlayer)
    # 每日任务奖励
    elif rewardType == ChConfig.Def_RewardType_DailyTask:
        PlayerActivity.GetDailyTaskAward(curPlayer, dataEx)
    # 成就奖励
    elif rewardType == ChConfig.Def_RewardType_Success:
        PlayerSuccess.GetSuccessAward(curPlayer, dataEx)
    # 仙树免费减时
    elif rewardType == ChConfig.Def_RewardType_TreeFreeTime:
        PlayerTree.FreeReduceTreeLVTime(curPlayer)
        PlayerTree.FreeReduceTreeLVTime(curPlayer, dataEx)
    # 广告奖励
    elif rewardType == ChConfig.Def_RewardType_ADAward:
        OnGetADAward(curPlayer, dataEx)
    # 历练秘笈升级
    elif rewardType == ChConfig.Def_RewardType_LLMJLVUp:
        PlayerLLMJ.OnLLMJLVUp(curPlayer)
    # 公会讨伐领取宝箱奖励
    elif rewardType == ChConfig.Def_RewardType_FamilyTaofaBox:
        PlayerFamilyTaofa.GetTaofaBoxAward(curPlayer)
    # 阵容推荐奖励
    elif rewardType == ChConfig.Def_RewardType_LineupRecommend:
        PlayerHero.GetLineupRecommendAward(curPlayer, dataEx, dataExStr)
    # 功能开启奖励
    elif rewardType == ChConfig.Def_RewardType_OpenFunc:
        GameFuncComm.GetFuncOpenAward(curPlayer, dataEx)
    # 红颜等级奖励
    elif rewardType == ChConfig.Def_RewardType_BeautyLVAward:
        PlayerBeauty.GetBeautyLVAward(curPlayer, dataEx)
    # 领取分包下载奖励
    elif rewardType == ChConfig.Def_RewardType_DownLoad:
        GetDownloadAward(curPlayer, dataEx)
    # 开服庆典积分阶段奖励
    elif rewardType == ChConfig.Def_RewardType_OSACelebrationPointAward:
        OpenServerActivity.GetOSACelebrationPointAward(curPlayer, dataEx)
    # 轮回殿奖励
    elif rewardType == ChConfig.Def_RewardType_LunhuidianAward:
        PlayerActLunhuidian.GetLunhuidianAward(curPlayer, dataEx, dataExStr)
    # 每日免费直购礼包
    elif rewardType == ChConfig.Def_RewardType_DayFreeGoldGift:
        PlayerDailyGiftbag.OnGetDailyFreeGiftbag(curPlayer)
    # 仙盟每日福利奖励
    elif rewardType == ChConfig.Def_RewardType_FamilyDayAward:
        PlayerFamily.GetFamilyDayAward(curPlayer)
    # 玩家等级奖励
    elif rewardType == ChConfig.Def_RewardType_LVAward:
        PlayerLVAward.GetPlayerLVAward(curPlayer, dataEx)
@@ -3298,9 +3416,6 @@
    # 领取极品白拿
    elif rewardType == ChConfig.Def_RewardType_FreeGoods:
        PlayerFreeGoods.OnGetFreeGoods(curPlayer, dataEx)
    # 领取消费返利奖励
    elif rewardType == ChConfig.Def_RewardType_CostRebate:
        PlayerCostRebate.OnGetCostRebateAward(curPlayer, dataEx, dataExStr)
    # 领取累计充值奖励
    elif rewardType == ChConfig.Def_RewardType_TotalRecharge:
        PlayerActTotalRecharge.OnGetTotalRechargeAward(curPlayer, dataEx, dataExStr)
@@ -3310,39 +3425,15 @@
    # 领取单笔累充领取
    elif rewardType == ChConfig.Def_RewardType_SingleRecharge:
        PlayerActSingleRecharge.OnGetSingleRechargeAward(curPlayer, dataEx, dataExStr)
    # 领取boss复活活动奖励
    elif rewardType == ChConfig.Def_RewardType_BossReborn:
        PlayerBossReborn.GetBossRebornActionAward(curPlayer, dataEx)
    # 领取分包下载奖励
    elif rewardType == ChConfig.Def_RewardType_DownLoad:
        GetDownloadAward(curPlayer, dataEx)
    # 领取许愿池奖励
    elif rewardType == ChConfig.Def_RewardType_WishingWell:
        PlayerWishingWell.DoGetWishingAward(curPlayer)
    # 功能开启奖励
    elif rewardType == ChConfig.Def_RewardType_OpenFunc:
        GameFuncComm.GetFuncOpenAward(curPlayer, dataEx)
    # 领取周狂欢活动奖励
    elif rewardType == ChConfig.Def_RewardType_WeekPartyAct:
        PlayerWeekParty.GetWeekPartyActionAward(curPlayer, dataEx, dataExStr)
    # 领取周狂欢积分奖励
    elif rewardType == ChConfig.Def_RewardType_WeekPartyPoint:
        PlayerWeekParty.GetWeekPartyPointAward(curPlayer, dataEx, dataExStr)
    # 领取登录奖励活动奖励
    elif rewardType == ChConfig.Def_RewardType_ActLoginAwardAct:
        PlayerActLogin.GetLoginAwardActionAward(curPlayer, dataEx, dataExStr)
    # 领取节日巡礼活动奖励
    elif rewardType == ChConfig.Def_RewardType_FeastWeekPartyAct:
        PlayerFeastWeekParty.GetFeastWeekPartyActionAward(curPlayer, dataEx, dataExStr)
    # 领取节日巡礼积分奖励
    elif rewardType == ChConfig.Def_RewardType_FeastWeekPartyPoint:
        PlayerFeastWeekParty.GetFeastWeekPartyPointAward(curPlayer, dataEx, dataExStr)
    # 领取节日登录奖励
    elif rewardType == ChConfig.Def_RewardType_FeastLogin:
        PlayerFeastLogin.GetFeastLoginAward(curPlayer, dataEx)
    # 领取节日游历奖励
    elif rewardType == ChConfig.Def_RewardType_FeastTravel:
        PlayerFeastTravel.GetFeastTravelAward(curPlayer, dataEx)
    # 领取登录活动奖励
    elif rewardType == ChConfig.Def_RewardType_ActLoginAwardNew:
        PlayerActLoginNew.OnGetActLoginAward(curPlayer, dataEx, dataExStr)
@@ -3352,21 +3443,6 @@
    # 领取任务活动奖励
    elif rewardType == ChConfig.Def_RewardType_ActTask:
        PlayerActTask.OnGetActTaskAward(curPlayer, dataEx, dataExStr)
    # 领取跨服充值排行活动达标奖励
    elif rewardType == ChConfig.Def_RewardType_CACTGBillboardDabiao:
        CrossActCTGBillboard.GetDabiaoAward(curPlayer, dataEx)
    # 跨服全民充值奖励
    elif rewardType == ChConfig.Def_RewardType_CAAllRecharge:
        CrossActAllRecharge.GetCrossActAllRechargeAward(curPlayer, dataEx)
    # 跨服妖魔boss伤害奖励
    elif rewardType == ChConfig.Def_RewardType_CrossYaomoBossHurt:
        PlayerCrossYaomoBoss.GetCrossYaomoBossHurtAward(curPlayer, dataEx, tick)
    # 古宝特殊效果物品奖励
    elif rewardType == ChConfig.Def_RewardType_GubaoItemEff:
        PlayerGubao.GetGubaoItemEffAward(curPlayer, dataEx, dataExStr)
    # 成就积分奖励
    elif rewardType == ChConfig.Def_RewardType_SuccessScore:
        PlayerSuccess.GetSuccessScoreAward(curPlayer, dataEx)
    # 买一送多活动免费奖励
    elif rewardType == ChConfig.Def_RewardType_BuyOne:
        PlayerActBuyOne.GetBuyOneFreeAward(curPlayer, dataEx, dataExStr)
@@ -3382,15 +3458,9 @@
    # 寻宝累计次数奖励
    elif rewardType == ChConfig.Def_RewardType_TreasureCntAward:
        PlayerTreasure.GetTreasureCntAward(curPlayer, dataEx, dataExStr)
    # 轮回殿奖励
    elif rewardType == ChConfig.Def_RewardType_LunhuidianAward:
        PlayerActLunhuidian.GetLunhuidianAward(curPlayer, dataEx, dataExStr)
    #历史累计充值领取
    elif rewardType == ChConfig.Def_RewardType_HistoryChargeAward:
        PlayerGoldGift.OnGetHistoryRechargeAward(curPlayer, dataEx)
    #在线特惠充值额外奖励
    elif rewardType == ChConfig.Def_RewardType_OnlineRechargeTH:
        PlayerCoin.OnGetOnlineRechargeTH(curPlayer)
    #创角奖励
    elif rewardType == ChConfig.Def_RewardType_CreateRole:
        OnGetCreateRoleAward(curPlayer)
@@ -3438,22 +3508,34 @@
        return
    adCntMax = ipyData.GetADCntMax()
    adCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ADCnt % adID)
    if adCnt >= adCntMax:
    if adCntMax and adCnt >= adCntMax:
        GameWorld.DebugLog("今日该广告奖励已达上限! adID=%s,adCnt=%s > %s" % (adID, adCnt, adCntMax))
        return
    adCnt += 1
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ADCnt % adID, adCnt)
    awardItemList = ipyData.GetADAwardItemList()
    adMapID = ipyData.GetADMapID()
    GameWorld.DebugLog("领取广告奖励! adID=%s,adCnt=%s,adMapID=%s,awardItemList=%s" % (adID, adCnt, adMapID, awardItemList))
    adAwardType = ipyData.GetADAwardType()
    adAwardValue = ipyData.GetADAwardValue()
    GameWorld.DebugLog("领取广告奖励! adID=%s,adCnt=%s,adAwardType=%s,adAwardValue=%s,awardItemList=%s" % (adID, adCnt, adAwardType, adAwardValue, awardItemList))
    SyncADCntInfo(curPlayer, [adID])
    
    if adMapID:
        FBCommon.AddFBADCnt(curPlayer, adMapID)
    if awardItemList:
        ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["ADAward", False, {}])
        
    # 领取祝福树充能奖励
    if adAwardType == 1:
        PlayerTree.GetTreeEnergyAward(curPlayer, False)
    # 副本次数
    elif adAwardType == 2:
        adMapID = adAwardValue
        FBCommon.AddFBADCnt(curPlayer, adMapID)
    # 寻宝
    elif adAwardType == 3:
        treasureType = adAwardValue
        PlayerTreasure.DoTreasure(curPlayer, treasureType, PlayerTreasure.CostType_ADFree)
    # 游历体力
    elif adAwardType == 4:
        PlayerTravel.AddTravelEnergy(curPlayer, adAwardValue)
    return
def ADCntOnDay(curPlayer):
@@ -3482,7 +3564,7 @@
        adCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ADCnt % adID)
        if not adCnt and syncADIDList == None:
            continue
        adInfo = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCADInfo)
        adInfo = ChPyNetSendPack.tagSCADInfo()
        adInfo.ADID = adID
        adInfo.ADCnt = adCnt
        adInfoList.append(adInfo)
@@ -3490,7 +3572,7 @@
    if not adInfoList:
        return
    
    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCADInfoList)
    clientPack = ChPyNetSendPack.tagSCADInfoList()
    clientPack.ADInfoList = adInfoList[:255]
    clientPack.Count = len(clientPack.ADInfoList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
@@ -3534,6 +3616,37 @@
    sendPack = ChPyNetSendPack.tagMCCreateRoleAwardState()
    sendPack.Clear()
    sendPack.GetState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CreateRoleAwardState)
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
def GetDownloadAward(curPlayer, dataEx):
    ##分包下载奖励 dataEx 0直接领取 1发邮件
    playerID = curPlayer.GetPlayerID()
    downloadAwardNum = IpyGameDataPY.GetFuncCfg('DownReward', 2)
    curAwardNum = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DownloadAwardState)
    if curAwardNum == downloadAwardNum:
        GameWorld.DebugLog("已领取分包奖励! curAwardNum(%s) == downloadAwardNum(%s)" % (curAwardNum, downloadAwardNum), playerID)
        return
    awardItemList = IpyGameDataPY.GetFuncEvalCfg('DownReward', 1)
    if not awardItemList:
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DownloadAwardState, downloadAwardNum)
    GameWorld.DebugLog("领取分包下载奖励: curAwardNum=%s,downloadAwardNum=%s" % (curAwardNum, downloadAwardNum), playerID)
    if dataEx == 1:
        PlayerMail.SendMailByKey('SubpackageDownload', curPlayer.GetID(), awardItemList)
    else:
        ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["PackDownload", False, {}])
    SyncPackDownloadAward(curPlayer)
    return
def SyncPackDownloadAward(curPlayer):
    #分包下载奖励记录通知
    downloadAwardNum = IpyGameDataPY.GetFuncCfg('DownReward', 2)
    sendPack = ChPyNetSendPack.tagMCPackDownloadRecord()
    sendPack.Clear()
    sendPack.Record = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DownloadAwardState) == downloadAwardNum
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
@@ -3765,7 +3878,7 @@
#  @param curPlayer 
#  @param tick 时间戳
#  @return None
def Sync_PyServerDataTimeToClient(curPlayer):
def Sync_PyServerDataTimeToClient(curPlayer=None):
    # 服务器时间
    serverTime = GameWorld.GetCurrentTime()
    if not serverTime:
@@ -3780,10 +3893,13 @@
    serverDateTime.Minute = serverTime.minute
    serverDateTime.Second = serverTime.second
    serverDateTime.MicSecond = serverTime.microsecond
    serverDateTime.CrossServerTime = GameWorld.GetCrossServerTimeStr()
    serverDateTime.CrossServerTime = GameWorld.ChangeTimeNumToStr(CrossMgr.GetSSServerMgr().GetCrossTime())
    
    # 通知客户端同步时间
    NetPackCommon.SendFakePack(curPlayer, serverDateTime)
    if curPlayer:
        NetPackCommon.SendFakePack(curPlayer, serverDateTime)
    else:
        NetPackCommon.SendFackPackOnline(serverDateTime)
    return
## 通知开服天数
@@ -3808,24 +3924,6 @@
    clientPack.NowMicSecond = serverTime.microsecond
    clientPack.WeekOfYear = GameWorld.GetWeekOfYear()
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    #旧包先保留,之后删除
    gw = GameWorld.GetGameWorld()
    packData = ChPyNetSendPack.tagOpenServerDay()
    packData.Clear()
    packData.Day = gw.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay)
    packData.IsMixServer = gw.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_IsMixServer)
    packData.MixDay = gw.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_MixServerDay)
    packData.OpenWeekday = gw.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_OpenServerWeekday)
    packData.NowYear = serverTime.year
    packData.NowMonth = serverTime.month
    packData.NowDay = serverTime.day
    packData.NowHour = serverTime.hour
    packData.NowMinute = serverTime.minute
    packData.NowSecond = serverTime.second
    packData.NowMicSecond = serverTime.microsecond
    packData.WeekOfYear = GameWorld.GetWeekOfYear()
    NetPackCommon.SendFakePack(curPlayer, packData)
    return
#===============================================================================
@@ -3849,9 +3947,9 @@
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    
    #防外挂 不可移动
    if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
                                      == ChConfig.Def_AutoCheck_State_Danger:
        return
    #if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
    #                                  == ChConfig.Def_AutoCheck_State_Danger:
    #    return
    if not PYPlayerNormalMove(curPlayer, clientPack, tick):
        posX, posY = curPlayer.GetPosX(), curPlayer.GetPosY()
@@ -3959,16 +4057,6 @@
    curPlayer.ChangePos(sendPack_SeverPosX, sendPack_SeverPosY)
    PyNotifyPlayerMove(curPlayer, moveDir, clientPosX, clientPosY, sendPack_SeverPosX, sendPack_SeverPosY, moveType)
    curPlayer.SetClientMoveTick(sendPack_WorldTick)
    # 后面必须返回True
    fightPet = curPlayer.GetPetMgr().GetFightPet()
    if fightPet:
        #出战宠物同时移动
        if moveType == 0 or tick - fightPet.GetActionTick() > 300:
            PetControl.FightPetFollowMove(curPlayer,sendPack_SeverPosX, sendPack_SeverPosY)
            fightPet.SetCurAction(IPY_GameWorld.laNPCNull)
    return True
@@ -4004,64 +4092,6 @@
    sendPack.MoveType = moveType
    # NotifyAll 做过滤或者数量处理
    PlayerControl.PyNotifyAll(curPlayer, sendPack, False, 0)
    return
def GiveDownloadPatchAward(curPlayer):
    ## 发放下载补丁包奖励
    playerID = curPlayer.GetPlayerID()
    patchAwardNum = IpyGameDataPY.GetFuncCfg('DownReward', 4)
    curAwardNum = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DownloadPatchAward)
    if curAwardNum == patchAwardNum:
        GameWorld.DebugLog("已发放下载补丁包奖励! curAwardNum(%s) == patchAwardNum(%s)" % (curAwardNum, patchAwardNum), playerID)
        return
    awardItemList = IpyGameDataPY.GetFuncEvalCfg('DownReward', 3)
    if not awardItemList:
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DownloadPatchAward, patchAwardNum)
    GameWorld.DebugLog("发放补丁包下载奖励: curAwardNum=%s,patchAwardNum=%s" % (curAwardNum, patchAwardNum), playerID)
    PlayerControl.SendMailByKey("DownloadPatchAward", [playerID], awardItemList)
    return
def GetDownloadAward(curPlayer, dataEx):
    ##分包下载奖励 dataEx 0直接领取 1发邮件
    playerID = curPlayer.GetPlayerID()
    downloadAwardNum = IpyGameDataPY.GetFuncCfg('DownReward', 5)
    curAwardNum = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DownloadAwardState)
    if curAwardNum == downloadAwardNum:
        GameWorld.DebugLog("已领取分包奖励! curAwardNum(%s) == downloadAwardNum(%s)" % (curAwardNum, downloadAwardNum), playerID)
        return
    awardItemList = IpyGameDataPY.GetFuncEvalCfg('DownReward', 1)
    if not awardItemList:
        return
    # 检查背包
    if dataEx == 0:
        needSpace = len(awardItemList)
        packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace)
        if needSpace > packSpace:
            PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_998371")
            return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_DownloadAwardState, downloadAwardNum)
    GameWorld.DebugLog("领取分包下载奖励: curAwardNum=%s,downloadAwardNum=%s" % (curAwardNum, downloadAwardNum), playerID)
    if dataEx == 1:
        PlayerControl.SendMailByKey('SubpackageDownload', [curPlayer.GetID()], awardItemList)
    else:
        for itemID, itemCnt, isBind in awardItemList:
            ItemControler.GivePlayerItem(curPlayer, itemID, itemCnt, 0, [IPY_GameWorld.rptItem])
    SyncPackDownloadAward(curPlayer)
    return
def SyncPackDownloadAward(curPlayer):
    #分包下载奖励记录通知
    downloadAwardNum = IpyGameDataPY.GetFuncCfg('DownReward', 5)
    sendPack = ChPyNetSendPack.tagMCPackDownloadRecord()
    sendPack.Clear()
    sendPack.Record = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DownloadAwardState) == downloadAwardNum
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
def NotifyPlayerMove(curPlayer, posX, posY, npcID=0):