#!/usr/bin/python
# -*- coding: GBK -*-
#---------------------------------------------------------------------
##@package PlayerTeam
# @todo: Íæ¼Ò×é¶ÓÂß¼¹ÜÀíÆ÷
#
# @author: panwei
# @date 2010-05-10
# @version 1.0
#
# @note: 
#---------------------------------------------------------------------
#
#---------------------------------------------------------------------
#"""Version = 2015-07-17 13:50"""
#---------------------------------------------------------------------
#import PlayerRequest
import GameWorldBoss
import IpyGameDataPY
import NetPackCommon
import IPY_GameServer
import ChGameToMapPyPack
import ChPyNetSendPack
import DataRecordPack
import PlayerControl
import ShareDefine
import PyGameData
import GameWorld
import ChConfig
import PlayerFB
import copy
import time
import random
#---------------------------------------------------------------------
TeamFBAskType_Match = 0 # ×é¶Ó¸±±¾½øÈëѯÎÊÀàÐÍ - Æ¥Åä
TeamFBAskType_Enter = 1 # ×é¶Ó¸±±¾½øÈëѯÎÊÀàÐÍ - µã»÷½øÈë
TeamFBAskType_PrepareOK = 2 # ×é¶Ó¸±±¾½øÈëѯÎÊÀàÐÍ - ×¼±¸Íê±ÏºóÑéÖ¤
# ¶ÓÎé³ÉÔ±×¼±¸×´Ì¬
TeamMemPrepareStateList = (
TeamMemPrepareState_None,       # 0 δ֪
TeamMemPrepareState_OK,         # 1 ÒÑ×¼±¸
TeamMemPrepareState_Refuse,     # 2 ¾Ü¾ø
TeamMemPrepareState_Offline,    # 3 µôÏß
TeamMemPrepareState_LeaveTeam,  # 4 Í˳ö¶ÓÎé, ÈçÎÞÍÑ»úʱ¼äµôÏßµÈ
) = range(5)
## ¶ÓÎéÏà¹ØÏà¹ØÉóºË¿ª¹Ø×´Ì¬
def SetTeamCheckState(curPlayer, checkState):
    curPlayer.SetExAttr2(checkState)
    GameWorld.DebugLog("¶ÓÎéÏà¹ØÏà¹ØÉóºË¿ª¹Ø×´Ì¬±ä¸ü: %s" % checkState, curPlayer.GetPlayerID())
    return
## ÇëÇó¼ÓÈë¶ÓÎéÊÇ·ñÐèÒªÉóºË
def IsTeamJoinReqNeedCheck(curPlayer): return curPlayer.GetExAttr2() / 10
## ÑûÇë×é¶ÓÊÇ·ñÐèÒªÉóºË
def IsTeamInvateNeedCheck(curPlayer): return curPlayer.GetExAttr2() % 10
## ³¡¾°µØÍ¼ID¶ÓÎéID×Öµä
def GetSceneTeamIDDict(): return PyGameData.g_sceneTeamIDDict
def AddTeamIDToSceneList(teamID, mapID, tick):
    '''Ìí¼Ó¶ÓÎéIDµ½³¡¾°¶ÓÎéÁбíÖÐ
    ´´½¨¶ÓÎé¡¢¶Ó³¤±ä¸ü¡¢¶Ó³¤Çл»µØÍ¼¡¢ÉÏÏßʱ¶ÓÎéÖ»ÓÐÒ»ÈË
    '''
    teamIDList = PyGameData.g_sceneTeamIDDict.get(mapID, [])
    if teamID not in teamIDList:
        teamIDList.append(teamID)
        PyGameData.g_sceneTeamIDDict[mapID] = teamIDList
        GameWorld.DebugLog("Ìí¼Ó³¡¾°¶ÓÎé: mapID=%s,teamID=%s,sceneTeam=%s" % (mapID, teamID, PyGameData.g_sceneTeamIDDict))
        #UpdSceneTeamVersion(mapID, tick)
    return
def DelTeamIDFromSceneList(teamID, tick):
    '''°Ñ¶ÓÎéID´Ó³¡¾°¶ÓÎéÁбíÖÐÒÆ³ý
    ɾ³ý¶ÓÎé¡¢¶Ó³¤±ä¸ü¡¢¶Ó³¤Çл»µØÍ¼¡¢ÏÂÏßʱ¶ÓÎéÖ»ÓÐÒ»ÈË
    '''
    for mapID, teamIDList in PyGameData.g_sceneTeamIDDict.items():
        if teamID in teamIDList:
            teamIDList.remove(teamID)
            if not teamIDList:
                PyGameData.g_sceneTeamIDDict.pop(mapID)
            GameWorld.DebugLog("ɾ³ý³¡¾°¶ÓÎé: mapID=%s,teamID=%s,sceneTeam=%s" % (mapID, teamID, PyGameData.g_sceneTeamIDDict))
            #UpdSceneTeamVersion(mapID, tick)
            if teamID in PyGameData.g_tagMapTeamTimeDict:
                UpdateTeamTagMapTime(teamID, mapID)
            break
    return
#def UpdSceneTeamVersion(mapID, tick):
#    '''³¡¾°¶ÓÎéÐÅÏ¢¿ÉÄܱä¸üµÄÇé¿ö
#    ´´½¨¶ÓÎ顢ɾ³ý¶ÓÎé¡¢¶Ó³¤±ä¸ü¡¢¶Ó³¤Çл»µØÍ¼¡¢Ôö¼Ó³ÉÔ±¡¢É¾³ý³ÉÔ±¡¢¸ü¸Ä¶ÓÎéÐÅÏ¢
#    '''
#    PyGameData.g_sceneTeamServerVersion[mapID] = tick
#    GameWorld.DebugLog("³¡¾°¶ÓÎéÐÅÏ¢°æ±¾±ä¸ü: mapID=%s,version=%s, %s" % (mapID, tick, PyGameData.g_sceneTeamServerVersion))
#    return
def GetScenePlayerIDDict(): return PyGameData.g_scenePlayerIDDict
def AddPlayerIDToSceneList(playerID, mapID):
    '''Ìí¼ÓÍæ¼ÒIDµ½³¡¾°Íæ¼ÒÁбíÖÐ
    ÉÏÏß¡¢Çл»µØÍ¼
    '''
    playerIDList = PyGameData.g_scenePlayerIDDict.get(mapID, [])
    if playerID not in playerIDList:
        playerIDList.append(playerID)
        PyGameData.g_scenePlayerIDDict[mapID] = playerIDList
        GameWorld.DebugLog("Ìí¼Ó³¡¾°Íæ¼Ò: mapID=%s,playerID=%s,scenePlayerID=%s" 
                           % (mapID, playerID, PyGameData.g_scenePlayerIDDict))
    return
def DelPlayerIDFromSceneList(playerID):
    '''°ÑÍæ¼ÒID´Ó³¡¾°Íæ¼ÒÁбíÖÐÒÆ³ý
    ÏÂÏß¡¢Çл»µØÍ¼
    '''
    for mapID, playerIDList in PyGameData.g_scenePlayerIDDict.items():
        if playerID in playerIDList:
            playerIDList.remove(playerID)
            if not playerIDList:
                PyGameData.g_scenePlayerIDDict.pop(mapID)
            GameWorld.DebugLog("ɾ³ý³¡¾°Íæ¼Ò: mapID=%s,playerID=%s,scenePlayerID=%s" 
                               % (mapID, playerID, PyGameData.g_scenePlayerIDDict))
            break
    return
## Ä¿±êµØÍ¼¶ÓÎéID×Öµä
def AddTeamIDToTagMapTeamDict(teamID, tagMapID):
    ## ´´½¨¶ÓÎé¡¢¸Ä±ä¶ÓÎéÄ¿±ê¡¢ÉÏÏßʱ¶ÓÎéÖ»ÓÐÒ»ÈË
    teamIDList = PyGameData.g_tagMapTeamDict.get(tagMapID, [])
    if teamID not in teamIDList:
        teamIDList.append(teamID)
        PyGameData.g_tagMapTeamDict[tagMapID] = teamIDList
        GameWorld.DebugLog("Ìí¼ÓÄ¿±ê¶ÓÎé: tagMapID=%s,teamID=%s,tagMapTeam=%s" 
                           % (tagMapID, teamID, PyGameData.g_tagMapTeamDict))
    if tagMapID:
        UpdateTeamTagMapTime(teamID, tagMapID, True)
    return
def DelTeamIDFromTagMapTeamDict(teamID):
    ## ɾ³ý¶ÓÎé¡¢¸Ä±ä¶ÓÎéÄ¿±ê¡¢ÏÂÏßʱ¶ÓÎéÖ»ÓÐÒ»ÈË
    for tagMapID, teamIDList in PyGameData.g_tagMapTeamDict.items():
        if teamID in teamIDList:
            teamIDList.remove(teamID)
            if not teamIDList:
                PyGameData.g_tagMapTeamDict.pop(tagMapID)
            GameWorld.DebugLog("ɾ³ýÄ¿±ê¶ÓÎé: tagMapID=%s,teamID=%s,tagMapTeam=%s" 
                               % (tagMapID, teamID, PyGameData.g_tagMapTeamDict))
            if teamID in PyGameData.g_tagMapTeamTimeDict:
                PyGameData.g_tagMapTeamTimeDict.pop(teamID)
    return
def UpdateTeamTagMapTime(teamID, tagMapID, isForce=False):
    lastTime = 0
    if not isForce and teamID in PyGameData.g_tagMapTeamTimeDict:
        mapID, lastTime = PyGameData.g_tagMapTeamTimeDict[teamID]
        if tagMapID != mapID:
            #GameWorld.DebugLog("·Ç¶ÓÎéÄ¿±êµØÍ¼£¬²»¸üÐÂʱ¼ä! tagMapID=%s,mapID=%s" % (tagMapID, mapID))
            return
    curTime = time.time()
    PyGameData.g_tagMapTeamTimeDict[teamID] = [tagMapID, curTime]
    GameWorld.DebugLog("¸üжÓÎéÄ¿±êʱ¼ä: teamID=%s,tagMapID=%s,curTime=%s,lastTime=%s" % (teamID, tagMapID, curTime, lastTime))
    return
def ResetTeamTagMapByTime():
    curTime = time.time()
    teamMgr = GameWorld.GetTeamManager()
    for teamID, tagMapTimeInfo in PyGameData.g_tagMapTeamTimeDict.items():
        tagMapID, lastTime = tagMapTimeInfo
        if curTime - lastTime < 1200:
            continue
        if IsTeamMatchingPlayer(teamID):
            continue
        team = teamMgr.FindTeam(teamID)
        if not team:
            continue
        if DoChangeTeamTagMap(None, team, 0):
            GameWorld.DebugLog("ÖØÖöÓÎéÄ¿±ê! teamID=%s,tagMapID=%s,curTime=%s,lastTime=%s" % (teamID, tagMapID, curTime, lastTime))
    return
## ¸±±¾Æ¥ÅäÖеĶÓÎéID
def AddTeamIDToMatchingList(curTeam, tagMapID, tagMapEx):
    ## ¿ªÊ¼Æ¥Åäʱ¼ÓÈë
    key = (tagMapID, tagMapEx)
    teamID = curTeam.GetTeamID()
    teamIDList = PyGameData.g_matchingTeamDict.get(key, [])
    if teamID not in teamIDList:
        teamIDList.append(teamID)
        PyGameData.g_matchingTeamDict[key] = teamIDList
        # ͬ²½¿Í»§¶ËÆ¥Åä״̬
        statePack = ChPyNetSendPack.tagGCTeamMatchState()
        statePack.IsMatching = 1
        SendTeamFakePack(curTeam, statePack)
        GameWorld.DebugLog("Ìí¼ÓÆ¥Åä¶ÓÎé: tagMapID=%s,tagMapEx=%s,teamID=%s,matchingTeam=%s" 
                           % (tagMapID, tagMapEx, teamID, PyGameData.g_matchingTeamDict))
    return
def DelTeamIDFromMatchingList(curTeam):
    ## È¡ÏûÆ¥Åä¡¢ÂúԱʱ(Æ¥Åä¡¢·ÇÆ¥Åä)¡¢É¾³ý¶ÓÎé¡¢ÏÂÏßʱ¶ÓÎéÖ»ÓÐÒ»ÈË
    teamID = curTeam.GetTeamID()
    for key, teamIDList in PyGameData.g_matchingTeamDict.items():
        if teamID in teamIDList:
            tagMapID, tagMapEx = key
            teamIDList.remove(teamID)
            if not teamIDList:
                PyGameData.g_matchingTeamDict.pop(key)
            # ͬ²½¿Í»§¶ËÆ¥Åä״̬
            statePack = ChPyNetSendPack.tagGCTeamMatchState()
            SendTeamFakePack(curTeam, statePack)
            GameWorld.DebugLog("ɾ³ýÆ¥Åä¶ÓÎé: tagMapID=%s,tagMapEx=%s,teamID=%s,matchingTeam=%s" 
                               % (tagMapID, tagMapEx, teamID, PyGameData.g_matchingTeamDict))
    return
def IsTeamMatchingPlayer(teamID):
    for teamIDList in PyGameData.g_matchingTeamDict.values():
        if teamID in teamIDList:
            return True
    return False
## ¸±±¾Æ¥ÅäÖеÄÍæ¼ÒID
def AddPlayerIDToMatchingList(curPlayer, tagMapID, tagMapEx):
    ## ¿ªÊ¼Æ¥Åäʱ¼ÓÈë
    key = (tagMapID, tagMapEx)
    playerIDList = PyGameData.g_matchingPlayerDict.get(key, [])
    playerID = curPlayer.GetPlayerID()
    if playerID not in playerIDList:
        playerIDList.append(playerID)
        PyGameData.g_matchingPlayerDict[key] = playerIDList
        # ͬ²½¿Í»§¶ËÆ¥Åä״̬
        Sync_TeamMatchState(curPlayer, True)
        GameWorld.DebugLog("Ìí¼ÓÆ¥ÅäÍæ¼Ò: tagMapID=%s,tagMapEx=%s,playerID=%s,matchingPlayer=%s" 
                           % (tagMapID, tagMapEx, playerID, PyGameData.g_matchingPlayerDict))
    return
def DelPlayerIDFromMatchingList(curPlayer):
    ## È¡ÏûÆ¥Åä¡¢¼ÓÈë¶ÓÎé(Æ¥Åä¡¢·ÇÆ¥Åä)¡¢ÏÂÏß
    playerID = curPlayer.GetPlayerID()
    for key, playerIDList in PyGameData.g_matchingPlayerDict.items():
        if playerID in playerIDList:
            tagMapID, tagMapEx = key
            playerIDList.remove(playerID)
            if not playerIDList:
                PyGameData.g_matchingPlayerDict.pop(key)
            # ͬ²½¿Í»§¶ËÆ¥Åä״̬
            Sync_TeamMatchState(curPlayer, False)
            GameWorld.DebugLog("ɾ³ýÆ¥ÅäÍæ¼Ò: tagMapID=%s,tagMapEx=%s,playerID=%s,matchingPlayer=%s" 
                               % (tagMapID, tagMapEx, playerID, PyGameData.g_matchingPlayerDict))
    return
def IsPlayerMatchingTeam(playerID):
    for tagMapInfo, playerIDList in PyGameData.g_matchingPlayerDict.items():
        if playerID in playerIDList:
            return tagMapInfo
    return False
def Sync_TeamMatchState(curPlayer, isMatching):
    statePack = ChPyNetSendPack.tagGCTeamMatchState()
    statePack.IsMatching = int(isMatching)
    NetPackCommon.SendFakePack(curPlayer, statePack)
    return
#// B9 01 ´´½¨¶ÓÎé #tagCGCreateTeam
#
#struct    tagCGCreateTeam
#{
#    tagHead        Head;
#    DWORD        TagMapID;    // Ä¿±êµØÍ¼
#    WORD        TagMapEx;    // Ä¿±êµØÍ¼À©Õ¹
#    WORD        ReqMinLV;    // ¶ÓÔ±×îµÍµÈ¼¶ÏÞÖÆ
#    WORD        ReqMaxLV;    // ¶ÓÔ±×î¸ßµÈ¼¶ÏÞÖÆ
#};
def OnCreateTeam(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    tagMapID = clientData.TagMapID
    tagMapEx = clientData.TagMapEx
    reqMinLV = clientData.ReqMinLV
    reqMaxLV = clientData.ReqMaxLV
    
    #²»¿É×é¶Ó
    if not __CheckCanTeamComm(curPlayer):
        return
    
    curPlayerTeam = curPlayer.GetTeam()
    curPlayerID = curPlayer.GetPlayerID()
    
    if curPlayerTeam != None:
        # ÒÑÓжÓÎ飬²»ÄÜ´´½¨
        GameWorld.DebugLog("Íæ¼ÒÒÑÓжÓÎ飬²»ÄÜ´´½¨!", curPlayerID)
        return
    DoCreateTeam(curPlayer, tick, tagMapID, tagMapEx, reqMinLV, reqMaxLV)
    return
def DoCreateTeam(curPlayer, tick, tagMapID=0, tagMapEx=0, reqMinLV=1, reqMaxLV=0, isSync=True):    
    curPlayerID = curPlayer.GetPlayerID()
    if not reqMaxLV:
        reqMaxLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV")
    #×é³ÉжÓÎé
    curNewTeam = GameWorld.GetTeamManager().CreateTeam(IPY_GameServer.ttNormal, tagMapID, tagMapEx, reqMinLV, reqMaxLV)
    if curNewTeam == None:
        GameWorld.ErrLog("×î´ó¶ÓÎéÊýÁ¿ÒÑÂú, ´´½¨Ê§°Ü£¡", curPlayerID)
        return
    teamID = curNewTeam.GetTeamID()
    AddTeamIDToSceneList(teamID, curPlayer.GetMapID(), tick)
    AddTeamIDToTagMapTeamDict(teamID, tagMapID)
    
    #Ìí¼Ó³ÉÔ±
    curPlayer.SetTeam(curNewTeam)
    curNewTeam.AddMember(curPlayer)
    
    #ÉèÖõ±Ç°Íæ¼ÒΪ¶Ó³¤
    curNewTeamMenber = curNewTeam.GetMemberByID(curPlayerID)
    if curNewTeamMenber == None:
        GameWorld.ErrLog("ÉèÖõ±Ç°´´½¨¶ÓÎéÍæ¼ÒΪ¶Ó³¤, ÕÒ²»µ½Íæ¼Ò!teamID=%s" % teamID, curPlayerID)
        DR_Team("CreateError", teamID, {"Leader":curPlayerID, "tagMapID":tagMapID, "tagMapEx":tagMapEx, "reqMinLV":reqMinLV, "reqMaxLV":reqMaxLV})
        return
    
    __SetTeamLV(curNewTeamMenber, IPY_GameServer.tmlLeader, False)
    if isSync:
        Sync_TeamMemberInfo(curNewTeam)
        SyncMapServerTeamInfo(curNewTeam, "Create", {"Leader":curPlayerID, "tagMapID":tagMapID, "tagMapEx":tagMapEx, "reqMinLV":reqMinLV, "reqMaxLV":reqMaxLV})
        
    DelPlayerIDFromMatchingList(curPlayer)
    return curNewTeam
#// B9 02 ÑûÇëÍæ¼Ò¼ÓÈë¶ÓÎé #tagCGInvitePlayerJoinTeam
#
#struct    tagCGInvitePlayerJoinTeam
#{
#    tagHead        Head;
#    DWORD        PlayerID;        // Ä¿±êÍæ¼ÒID
#};
def OnInvitePlayerJoinTeam(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    tagPlayerID = clientData.PlayerID
    
    #ÑûÇëµÄÍæ¼Ò¶ÔÏó
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
    #Ä¿±êÍæ¼ÒÊÇ·ñ´æÔÚ
    if tagPlayer == None:
        GameWorld.Log("Ä¿±êÍæ¼Ò²»ÔÚÏß»ò²»´æÔÚ£¬ÎÞ·¨×é¶Ó£¡tagPlayerID=%s" % (tagPlayerID), playerID)
        PlayerControl.NotifyCode(curPlayer, "GeRen_hwj35_500807")
        return
    
    #»ñµÃË«·½µÄ¶ÓÎé
    curPlayerTeam = curPlayer.GetTeam()
    tagPlayerTeam = tagPlayer.GetTeam()
    
    #ÑûÇë×é¶ÓµÄʱºò£¬Ë«·½¶¼ÓжÓÎé²»´¦Àí
    if curPlayerTeam != None and tagPlayerTeam != None:
        #InviteEnterLost02  `oºÜ±§Ç¸,Ä¿±êÍæ¼ÒÒÑÔÚËûÈ˶ÓÎéÖÐ,ÑûÇëÈë¶Óʧ°Ü!  25  -   -
        #PlayerControl.NotifyCode(curPlayer, "InviteEnterLost02")
        InvitePlayerJoinTeamReq(curPlayer, tagPlayer, curPlayerTeam, tick)
        return
    
    if tagPlayerTeam == None:
        #Ä¿±êÍæ¼ÒûÓжÓÎé, ÑûÇëÍæ¼Ò¼ÓÈë, Ö§³ÖÎÞ¶ÓÎéË«·½ÎÞ¶ÓÎéÑûÇë
        InvitePlayerJoinTeamReq(curPlayer, tagPlayer, curPlayerTeam, tick)
        
    elif curPlayerTeam == None and tagPlayerTeam != None:
        #ÇëÇó¼ÓÈë¶ÓÎé(#±»ÑûÇëµÄÍæ¼ÒÓжӣ¬ÇëÇó¼ÓÈëÆä¶ÓÎé)
        RequestJoinTeamReq(curPlayer, tagPlayerTeam, tick)
        
    else:
        GameWorld.Log("OnInvitePlayerJoinTeam ->×é¶ÓϵͳÒì³£" , curPlayer.GetPlayerID())
        
    return
#//09 09 ÇëÇó¼ÓÈë¶ÓÎé#tagCRequestJoinTeam
#
#struct    tagCRequestJoinTeam
#{
#    tagHead        Head;
#    DWORD        PlayerID;
#};
def RequestJoinTeam(index, tick):
    #»ñµÃ·â°ü
    sendPack = IPY_GameServer.IPY_CRequestJoinTeam()
    #·¢³öÇëÇóµÄÍæ¼ÒID
    tagPlayerID = sendPack.GetPlayerID()
    __Func_RequestJoinTeam(index, tagPlayerID, tick)
    return
def __Func_RequestJoinTeam(index, tagPlayerID, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    
    
    #ÑûÇëµÄÍæ¼Ò¶ÔÏó
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
    #Ä¿±êÍæ¼ÒÊÇ·ñ´æÔÚ
    if tagPlayer == None:
        GameWorld.Log("Ä¿±ê×é¶ÓÍæ¼Ò²»ÔÚÏߣ¬ÎÞ·¨×é¶Ó£¡tagPlayerID=%s" % (tagPlayerID), playerID)
        PlayerControl.NotifyCode(curPlayer, "GeRen_hwj35_500807")
        return
    
    #»ñµÃË«·½µÄ¶ÓÎé
    #curPlayerTeam = curPlayer.GetTeam()
    tagPlayerTeam = tagPlayer.GetTeam()
        
    #ÇëÇó¼ÓÈëµÄʱºò£¬Ë«·½¶¼ÓжÓÎéÒ²¿ÉÇëÇó¼ÓÈ룬֧³ÖÍ˳ö¶ÓÎéÇëÇó¼ÓÈë
#    if curPlayerTeam != None and tagPlayerTeam != None:
#        #InviteEnterLost02  `oºÜ±§Ç¸,Ä¿±êÍæ¼ÒÒÑÔÚËûÈ˶ÓÎéÖÐ,ÑûÇëÈë¶Óʧ°Ü!  25  -   -
#        PlayerControl.NotifyCode(curPlayer, "InviteEnterLost02")
#        return
    if tagPlayerTeam == None:
        # TeamNoExist ¶ÓÎé²»´æÔÚ
        PlayerControl.NotifyCode(curPlayer, "TeamNoExist")
        #Ä¿±êÍæ¼ÒûÓжÓÎé, ÑûÇëÍæ¼Ò¼ÓÈë, Ö§³ÖÎÞ¶ÓÎéË«·½ÎÞ¶ÓÎéÑûÇë
        #InvitePlayerJoinTeamReq(curPlayer, tagPlayer, curPlayerTeam, tick)
    else:
        # ÇëÇó¼ÓÈë¶ÓÎé(#±»ÇëÇóµÄÍæ¼ÒÓжӣ¬ÇëÇó¼ÓÈëÆä¶ÓÎé)
        RequestJoinTeamReq(curPlayer, tagPlayerTeam, tick)
        
    return
def InvitePlayerJoinTeamReq(curPlayer, tagPlayer, curPlayerTeam, tick):
    '''ÑûÇëÍæ¼Ò¼ÓÈë/Ò»Æð×é¶Ó, Ö§³ÖË«·½ÎÞ¶ÓÎéÑûÇë
    @param curPlayer: ÑûÇë·½
    @param tagPlayer: ±»ÑûÇë·½
    @param curPlayerTeam: ÑûÇë·½µ±Ç°¶ÓÎ飬¿ÉÄÜΪNone
    '''
    if not __CheckCanTeamComm(curPlayer, tagPlayer):
        return
    
    tagMapID, tagMapEx = 0, 0 # ĬÈÏÎÞÄ¿±ê¶ÓÎé
    # Èç¹ûÑûÇë·½ÓжÓÎé
    if curPlayerTeam:
        #Åж϶ÓÎéÈËÊý
        if curPlayerTeam.IsTeamFull():
            #GeRen_chenxin_570355  ¶Ô²»Æð,ÎÒ·½¶ÓÎéÒÑÂúÔ±£¡
            PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_570355")
            return
        
        #²ß»®Ð޸ĹæÔò£¬ÈκζÓÔ±¶¼ÓÐÕÐÈËȨÏÞ
        #===========================================================================================
        # #ÅжÏÊÇ·ñÓÐȨÏÞ
        # if not CheckTeamLV(curPlayer):
        #    #ApplyEnterLost04   ¶Ô²»Æð,ÄúûÓÐÊÕÈËȨÏÞ,ÕÐÊÕ¶ÓԱʧ°Ü!    25  -   -  Ìí¼ÓÒ»ÏÂ
        #    PlayerControl.NotifyCode(curPlayer, "ApplyEnterLost04")
        #    return
        #===========================================================================================
        
        tagMapID = curPlayerTeam.GetTagMapID()
        tagMapEx = curPlayerTeam.GetTagMapEx()
    
    curPlayerID = curPlayer.GetPlayerID()
    tagPlayerID = tagPlayer.GetPlayerID()
    #Ìí¼ÓÆÕͨ×é¶ÓÇëÇó
    #curPlayer.AddRequest(tagPlayerID, IPY_GameServer.reqTeam, tick, ChConfig.Def_EventClearTime)
    #GameWorld.Log("Íæ¼Ò%sÌí¼Ó:ÑûÇë¼ÓÈëÆÕͨ×é¶ÓÇëÇó³É¹¦"%(curPlayerID), curPlayerID, tagPlayerID)
    #GameWorld.Log("Íæ¼Ò%sÌí¼Ó:ÑûÇë¼ÓÈëÆÕͨ×é¶ÓÇëÇó³É¹¦"%(tagPlayerID), curPlayerID, tagPlayerID)
    
    GameWorld.DebugLog("ÑûÇë×é¶Ó, tagMapID=%s,tagMapEx=%s,tagPlayerID=%s" % (tagMapID, tagMapEx, tagPlayerID), curPlayerID)
    
    isTjg = PlayerControl.GetIsTJG(tagPlayer)
    if (isTjg or not IsTeamInvateNeedCheck(tagPlayer)) and not tagPlayer.GetTeamID():
        GameWorld.DebugLog("±»ÑûÇëµÄÍæ¼Ò´¦ÓÚÍÑ»ú״̬»ò²»ÐèÒªÉóºËµÄ£¬Ö±½ÓÈë¶Ó! tagPlayerID=%s,isTjg=%s" 
                           % (tagPlayerID, isTjg), curPlayerID)
        DoPlayerJoinTeam(tagPlayer, curPlayer, curPlayerTeam, tick, curPlayer)
        return True
    
    #֪ͨ¿Í»§¶Ëµ¯´°¿Ú(Ä¿±êµ¯¿ò)
    #tagPlayer.TeamAskIfJoin(curPlayer.GetPlayerID(), curPlayer.GetName(), teamType) # //09 01 ¶Ó³¤ÑûÇëÍæ¼Ò¼ÓÈë¶ÓÎé#tagLeaderAskJoin
    invitePack = ChPyNetSendPack.tagGCInviteJoinTeamInfo()
    invitePack.PlayerID = curPlayerID
    invitePack.Name = curPlayer.GetName()
    invitePack.NameLen = len(invitePack.Name)
    invitePack.LV = curPlayer.GetLV()
    invitePack.Job = curPlayer.GetJob()
    invitePack.JobLevel = PlayerControl.GetJobRank(curPlayer)
    invitePack.RealmLV = curPlayer.GetOfficialRank()
    invitePack.TagMapID = tagMapID
    invitePack.TagMapEx = tagMapEx
    NetPackCommon.SendFakePack(tagPlayer, invitePack)
    
    #TeamInviteSuccess: Òѳɹ¦·¢ËÍ×é¶ÓÑûÇë
    PlayerControl.NotifyCode(curPlayer, "TeamInviteSuccess")
    return True
def RequestJoinTeamReq(curPlayer, tagPlayerTeam, tick):
    '''ÇëÇó¼ÓÈë¶ÓÎé
    @param curPlayer: ÇëÇó·½
    @param tagPlayerTeam: Ä¿±ê¶ÓÎé
    '''
    if not tagPlayerTeam:
        return
    
    # ÇëÇóÈë¶ÓµÄÐÅÏ¢ÍÆË͸øÄ¿±ê¶ÓÎé¶Ó³¤£¬Óɶӳ¤½øÐÐÉóºË
    tagPlayer = GetTeamLeader(tagPlayerTeam)
    if not tagPlayer:
        return
        
    if not __CheckCanTeamComm(curPlayer, tagPlayer):
        return
    
    if not (tagPlayerTeam.GetReqMinLV() <= curPlayer.GetLV() <= tagPlayerTeam.GetReqMaxLV()):
        PlayerControl.NotifyCode(curPlayer, "TeamAskLost")
        return
    
    #Åж϶ÓÎéÈËÊý
    if tagPlayerTeam.IsTeamFull():
        #GeRen_chenxin_227479  Ä¿±ê¶ÓÎéÒÑÂúÔ±£¡
        PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_227479")
        return
    
    curPlayerID = curPlayer.GetPlayerID()
    tagPlayerID = tagPlayer.GetPlayerID()
        
    #Ìí¼ÓÆÕͨ×é¶ÓÇëÇó
    #curPlayer.AddRequest(tagPlayerID, IPY_GameServer.reqTeam, tick, ChConfig.Def_EventClearTime)
    #GameWorld.Log("Íæ¼Ò%sÌí¼Ó:ÉêÇë¼ÓÈëÆÕͨ×é¶ÓÇëÇó³É¹¦"%(curPlayerID), curPlayerID, tagPlayerID)
    #GameWorld.Log("Íæ¼Ò%sÌí¼Ó:ÉêÇë¼ÓÈëÆÕͨ×é¶ÓÇëÇó³É¹¦"%(tagPlayerID), curPlayerID, tagPlayerID)
    
    GameWorld.DebugLog("ÇëÇó¼ÓÈë¶ÓÎé,teamID=%s,tagPlayerID=%s" % (tagPlayerTeam.GetTeamID(), tagPlayerID), curPlayerID)
    
    isTjg = PlayerControl.GetIsTJG(tagPlayer)
    if isTjg or not IsTeamJoinReqNeedCheck(tagPlayer):
        GameWorld.DebugLog("±»ÇëÇó¼ÓÈëµÄ¶Ó³¤´¦ÓÚÍÑ»ú״̬»ò²»ÐèÒªÉóºËµÄ£¬Ö±½ÓÈë¶Ó! tagPlayerID=%s,isTjg=%s" 
                           % (tagPlayerID, isTjg), curPlayerID)
        DoPlayerJoinTeam(curPlayer, tagPlayer, tagPlayerTeam, tick, curPlayer)
        return True
    
    #֪ͨ¿Í»§¶Ëµ¯´°¿Ú(Ä¿±êµ¯¿ò)
    #tagPlayer.PlayerJoinTeamAsk(curPlayer.GetPlayerID(), curPlayer.GetName()) # //09 07 ÊÇ·ñÔÊÐí¶ÓÔ±¼ÓÈë#tagPlayerAskJoinTeam
    requestPack = ChPyNetSendPack.tagGCRequestJoinTeam()
    requestPack.PlayerID = curPlayerID
    requestPack.Name = curPlayer.GetName()
    requestPack.NameLen = len(requestPack.Name)
    requestPack.LV = curPlayer.GetLV()
    requestPack.Job = curPlayer.GetJob()
    requestPack.JobLevel = PlayerControl.GetJobRank(curPlayer)
    requestPack.RealmLV = curPlayer.GetOfficialRank()
    NetPackCommon.SendFakePack(tagPlayer, requestPack)
    
    #TeamAskSuccess: Òѳɹ¦·¢ËÍÈë¶ÓÉêÇë
    PlayerControl.NotifyCode(curPlayer, "TeamAskSuccess")
    return True
def Sync_TeamMemberInfo(curTeam):
    olPlayerList = []
    teamMemberInfo = ChPyNetSendPack.tagGCTeamMemberInfo()
    teamMemberInfo.TeamID = curTeam.GetTeamID()
    teamMemberInfo.TagMapID = curTeam.GetTagMapID()
    teamMemberInfo.TagMapEx = curTeam.GetTagMapEx()
    teamMemberInfo.ReqMinLV = curTeam.GetReqMinLV()
    teamMemberInfo.ReqMaxLV = curTeam.GetReqMaxLV()
    teamMemberInfo.MemberList = []
    for i in xrange(curTeam.GetMemberCount()):
        memberInfo = curTeam.GetMemberInfo(i)
        playerID = memberInfo.GetPlayerID()
        if not playerID:
            continue
        member = ChPyNetSendPack.tagGCTeamMember()
        member.Index = i
        member.PlayerID = playerID
        member.Name = memberInfo.GetPlayerName()
        member.NameLen = len(member.Name)
        member.MemberLV = memberInfo.GetTeamLV()
        member.LV = memberInfo.GetPlayerLV()
        member.Job = memberInfo.GetPlayerJob()
        member.JobLevel = memberInfo.GetPlayerJobLevel()
        member.RealmLV = memberInfo.GetPlayerRealmLV()
        memberPlayer = curTeam.GetMemberPlayer(i)
        if memberPlayer and memberPlayer.GetPlayerID():
            member.PlayerState = not PlayerControl.GetIsTJG(memberPlayer) # 0: ÀëÏß 1:ÔÚÏß
            member.MapID = memberPlayer.GetMapID()
            member.LineID = memberPlayer.GetFBID()
            olPlayerList.append(memberPlayer)
            
        teamMemberInfo.MemberList.append(member)
    teamMemberInfo.MemberCount = len(teamMemberInfo.MemberList)
    
    for player in olPlayerList:
        NetPackCommon.SendFakePack(player, teamMemberInfo)
    return
def __CheckCanTeamComm(curPlayer, tagPlayer=None):
    # ×é¶Ó³£¹æÑéÖ¤
    
    curPlayerID = curPlayer.GetPlayerID()
    curMapID = curPlayer.GetMapID()
    curMapData = GameWorld.GetMap(curMapID)
    if not curMapData:
        return False
    #²»¿É×é¶Ó»ò±ä¸ü¶ÓÎé¹ØÏµµÄµØÍ¼
    if curMapData.GetTeamLimit() or curMapData.GetMapFBType() == ChConfig.fbtTeam:
        PlayerControl.NotifyCode(curPlayer, "GeRen_liubo_986912")
        return False
    
    curTeamID = curPlayer.GetTeamID()
    if IsInEnterFBTeamAsk(curTeamID):
        PlayerControl.NotifyCode(curPlayer, "TeamEnterForbid")
        return False
    if IsInEnterFBTeamPrepare(curTeamID):
        PlayerControl.NotifyCode(curPlayer, "TeamEnterForbid")
        return False
    
    if tagPlayer:
        tagPlayerID = tagPlayer.GetPlayerID()
        #¼ì²éID
        if curPlayerID == tagPlayerID:
            GameWorld.Log("Ä¿±êÍæ¼ÒID´íÎó£¬ÎÞ·¨ÑûÇ룡tagPlayerID=%s" % (tagPlayerID), curPlayerID)
            return False
        
        tagMapID = tagPlayer.GetMapID()
        tagMapData = GameWorld.GetMap(tagMapID)
        if not tagMapData:
            return False
        #½ÓÊÕ·½²»¿É×é¶Ó»ò±ä¸ü¶ÓÎé¹ØÏµµÄµØÍ¼
        if tagMapData.GetTeamLimit() or tagMapData.GetMapFBType() == ChConfig.fbtTeam:
            PlayerControl.NotifyCode(curPlayer, "GeRen_lwh_0")
            return False
        
        tagTeamID = tagPlayer.GetTeamID()
        if IsInEnterFBTeamAsk(tagTeamID):
            PlayerControl.NotifyCode(curPlayer, "TeamEnterForbid")
            return False
        if IsInEnterFBTeamPrepare(tagTeamID):
            PlayerControl.NotifyCode(curPlayer, "TeamEnterForbid")
            return False
        
    return True
#===============================================================================
# //09 03 ×é¶ÓÇëÇó»ØÓ¦#tagCTeamReq
# tagCTeamReq       *   GettagCTeamReq();
# 
# class   IPY_CTeamReq
# {
# public:
# 
#    int      GetPlayerID();
#    //×é¶ÓÀàÐÍ
#    int      GetTeamType();
#    //0 : ¾Ü¾ø 1 : ͬÒâ  2: ÎÞÏìÓ¦
#    int      GetType();
# };
#===============================================================================
##±»ÑûÇëµÄÍæ¼ÒÎÞ¶Ó£¬¼ÓÈë·¢³öÑûÇëÍæ¼Ò¶ÓÎ黨Ӧ
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //09 03 ×é¶ÓÇëÇó»ØÓ¦#tagCTeamReq; ±»ÈËÑûÇë¼ÓÈë¶ÓÎéʱµÄ»ØÓ¦
def TeamReqReply(index, tick):
    #»ñµÃ·â°ü
    sendPack = IPY_GameServer.IPY_CTeamReq()
    tagPlayerID = sendPack.GetPlayerID() # ·¢³öÑûÇëµÄÍæ¼ÒID
    isAgree = sendPack.GetType() # ÊÇ·ñͬÒâ
    __Func_TeamReqReply(index, tagPlayerID, isAgree, tick)
    return
def __Func_TeamReqReply(index, tagPlayerID, isAgree, tick):
    #±»ÑûÇëÍæ¼Ò
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    #·¢³öÑûÇëµÄÍæ¼Ò
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
    
    if tagPlayer == None:
        #GeRen_hwj35_500807 ¶Ô²»Æð,ÑûÇëÄã½øÈë¶ÓÎéµÄÍæ¼ÒÒѾÏÂÏß!
        PlayerControl.NotifyCode(curPlayer, "GeRen_hwj35_500807")
        return
    
    #Ë«·½µÄ¶ÓÎé
    #curPlayerTeam = curPlayer.GetTeam() 
    tagPlayerTeam = tagPlayer.GetTeam()
    
    if tagPlayerTeam == None:
        GameWorld.DebugLog("ÑûÇë×é¶ÓµÄ¶ÓÎéÒѾ²»´æÔÚ£¡")        
        PlayerControl.NotifyCode(curPlayer, "TeamNoExist")
        return
    
    #===============================================================================================
    # if curPlayerTeam != None:
    #    #InviteEnterLost02  ×é¶Óʧ°Ü£¬Ë«·½¶¼ÓжÓÎ飡
    #    PlayerControl.NotifyCode(curPlayer, "InviteEnterLost02")
    #    return
    #===============================================================================================
    
    #×é¶ÓÀàÐÍ
    #teamType = sendPack.GetTeamType()
    
    #ÊÇ·ñͬÒâ
    if isAgree != 1:
        #InviteEnterLost01  ÑûÇëÈë¶Óʧ°Ü£¬Ä¿±êÍæ¼Ò¾Ü¾øÁËÄúµÄÑûÇ룡
        PlayerControl.NotifyCode(tagPlayer, "InviteEnterLost01")
        return
    
    if not __CheckCanTeamComm(curPlayer, tagPlayer):
        return
    
    #===============================================================================================
    # #Á½¸öÍæ¼Ò×é³ÉжÓÎé(·¢³öÑûÇëµÄÍæ¼Ò,Ϊ¶Ó³¤)
    # if tagPlayerTeam == None:
    #    if not CreateNewTeam(curPlayer, tagPlayer, teamType):
    #        return False
    #    
    #    tagPlayerTeam = tagPlayer.GetTeam()
    #   
    # #¼ÓÈ뵱ǰ¶ÓÎé
    # else:
    #===============================================================================================
    DoPlayerJoinTeam(curPlayer, tagPlayer, tagPlayerTeam, tick, curPlayer)
    return
#---------------------------------------------------------------------
#===============================================================================
# //09 0A ÇëÇó¼ÓÈë×é¶Ó»ØÓ¦#tagCRequestJoinTeamReply
# tagCRequestJoinTeamReply       *   GettagCRequestJoinTeamReply();
# 
# class   IPY_CRequestJoinTeamReply
# {
# public:
# 
#    int      GetPlayerID();
#    //1:ͬÒâ 2:²»Í¬Òâ
#    int      GetType();
# };
#===============================================================================
##±»ÑûÇëµÄÍæ¼ÒÓжÓÎé,ÇëÇó¼ÓÈëÆä×é¶Ó»ØÓ¦
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //09 0A ÇëÇó¼ÓÈë×é¶Ó»ØÓ¦#tagCRequestJoinTeamReply; ¶ÓÎéÓÐÈËÇëÇó¼ÓÈëµÄ»ØÓ¦
def RequestJoinTeamReply(index, tick):
    #»ñµÃ·â°ü
    sendPack = IPY_GameServer.IPY_CRequestJoinTeamReply()
    #·¢³öÉêÇëµÄÍæ¼ÒID
    tagPlayerID = sendPack.GetPlayerID()
    isAgree = sendPack.GetType()
    __Func_RequestJoinTeamReply(index, tagPlayerID, isAgree, tick)
    return
def __Func_RequestJoinTeamReply(index, tagPlayerID, isAgree, tick):
    #±»ÑûÇëÍæ¼Ò(ÓжÓÎé)
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    #GameWorld.Log(str(tagPlayerID))
    #·¢³öÉêÇëµÄÍæ¼Ò
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
    
    if tagPlayer == None:
        #PK_hwj35_21675 ¶Ô²»Æð,ÉêÇë½øÈë¶ÓÎéµÄÍæ¼ÒÒÑÏÂÏß,²Ù×÷ÎÞЧ
        PlayerControl.NotifyCode(curPlayer, "PK_hwj35_21675")
        return
    
    #±»ÑûÇëµÄÍæ¼Ò¶ÓÎé
    curPlayerTeam = curPlayer.GetTeam()
    if curPlayerTeam == None:
        GameWorld.DebugLog("Íæ¼ÒÎÞ¶ÓÎ飬ÎÞ·¨ÉóºË¼ÓÈë¶ÓÎéÇëÇó!" , playerID)
        PlayerControl.NotifyCode(tagPlayer, "TeamNoExist")
        return
    
    #ÉêÇëÈë¶ÓµÄÔÊÐíË«·½¶¼ÓжÓÎé
#    #·¢³öÉêÇëµÄÍæ¼ÒµÄ¶ÓÎé
#    tagPlayerTeam = tagPlayer.GetTeam()
#    if tagPlayerTeam != None:
#        #InviteEnterLost02  ×é¶Óʧ°Ü£¬Ë«·½¶¼ÓжÓÎ飡
#        PlayerControl.NotifyCode(tagPlayer, "InviteEnterLost02")
#        return
    
    #===============================================================================================
    # #ÇëÇó¼ì²é,ÊÇ·ñÓÐÕâ¸öÇëÇó
    # if not PlayerRequest.CheckRequest(tagPlayer, curPlayer, IPY_GameServer.reqTeam):
    #    PlayerControl.NotifyCode(curPlayer, "InviteEnterLost03")
    #    return
    #===============================================================================================
    
    #È·Èϼì²é
    if isAgree != 1:
        #ApplyEnterLost02    ÉêÇëÈë¶Óʧ°Ü£¬¶Ô·½¾Ü¾øÁËÄú¼ÓÈë¸Ã¶ÓµÄÇëÇó£¡
        PlayerControl.NotifyCode(tagPlayer, "ApplyEnterLost02")
        return
    
    if not __CheckCanTeamComm(curPlayer, tagPlayer):
        return
        
    DoPlayerJoinTeam(tagPlayer, curPlayer, curPlayerTeam, tick, curPlayer)
    return True
def DoPlayerJoinTeam(joinPlayer, teamPlayer, tagTeam, tick, notifyPlayer=None, isAutoMatchJoin=False):
    ''' Ö´ÐÐÍæ¼Ò¼ÓÈë¶ÓÎé
    @param joinPlayer: ¼ÓÈë¶ÓÎéµÄÍæ¼Ò
    @param teamPlayer: ÉóºËÊÇ·ñÔÊÐí¼ÓÈëµÄ¶ÓÔ±£¬Ò»°ãÊǶӳ¤
    @param tagTeam: ¼ÓÈëµÄÄ¿±ê¶ÓÎé, ¿ÉÄÜΪNone
    @param notifyPlayer: ϵͳÐÅÏ¢·´À¡µÄÄ¿±êÍæ¼Ò£¬ ÇëÇó¼ÓÈëʱ·´À¡¸øÇëÇóµÄÍæ¼Ò£¬Èë¶Ó¼ÓÈëʱ·´À¡¸ø¶Ó³¤, Ϊ¿Õʱ²»×öÐÅÏ¢·´À¡
    @param isAutoMatchJoin: ÊÇ·ñ×Ô¶¯Æ¥Åä¼ÓÈëµÄ
    '''
    if not tagTeam:
        # ûÓжÓÎéµÄ»°ÏÈ´´½¨Ä¬È϶ÓÎé
        tagTeam = DoCreateTeam(teamPlayer, tick, isSync=False)
        if not tagTeam:
            return
        
    #===============================================================================================
    # #ÊÇ·ñÓÐÊÕÈËȨÏÞ
    # if not CheckTeamLV(teamPlayer):
    #    GameWorld.Log("Ä¿±êÍæ¼ÒÎÞÕÐÊÕ¶ÓԱȨÏÞ£¡")
    #    return
    #===============================================================================================
    
    #Åж϶ÓÎéÊÇ·ñÂúÈË
    if tagTeam.IsTeamFull():
        #GeRen_chenxin_227479  Ä¿±ê¶ÓÎéÒÑÂúÔ±£¡
        if notifyPlayer:
            PlayerControl.NotifyCode(notifyPlayer, "GeRen_chenxin_227479")
        return
    
    if tagTeam.GetMemberByID(joinPlayer.GetPlayerID()) != None:
        GameWorld.Log("ÒѾÓÐÕâ¸öÈË£¬²»ÐèÒªÖØÐ¼ÓÈ룡")
        return
    
    #Íæ¼Ò±¾ÉíÓжÓÎéʱ
    if joinPlayer.GetTeam():
        #===========================================================================================
        # if notifyPlayer:
        #    # AcceptTeamLost ¸ÃÍæ¼ÒÒÑÓжÓÎé
        #    PlayerControl.NotifyCode(notifyPlayer, "AcceptTeamLost")
        # return
        #===========================================================================================
        #ÏÈÍ˶Ó
        DoPlayerLeaveTeam(joinPlayer, joinPlayer.GetTeam(), tick)
        
    teamID = tagTeam.GetTeamID()
    GameWorld.Log("%s(%d)¼ÓÈë¶ÓÎé %s(%d), teamID=%s!" % (joinPlayer.GetName(), joinPlayer.GetPlayerID(), 
                                                     teamPlayer.GetName(), teamPlayer.GetPlayerID(), teamID))
    tagTeam.AddMember(joinPlayer)
    #UpdSceneTeamVersion(teamPlayer.GetMapID(), tick)
    
    #tagTeam.Sync_TeamState()
    Sync_TeamMemberInfo(tagTeam)
    
    #Çå¿ÕÇëÇó
#    PlayerRequest.DelRequest(curTagPlayer, curPlayer, requestType)
    #֪ͨMapServerd¶ÓÎé±ä¸ü
    #teamPlayer.MapServer_Sync_Team(__GetPlayerTeamLV(teamPlayer))
    #joinPlayer.MapServer_Sync_Team(__GetPlayerTeamLV(joinPlayer))
    SyncMapServerTeamInfo(tagTeam, "Join", {"teamPlayer":teamPlayer.GetPlayerID(), "joinPlayer":joinPlayer.GetPlayerID()})
    
    #֪ͨ
    #EnterProcession    <%S%>¼ÓÈëÁ˶ÓÎ飡  ¸ÄΪ GeRen_chenxin_543685
    #PlayerControl.NotifyCode(tagTeam, "GeRen_chenxin_543685", [joinPlayer.GetName()])
    
    #°ÑÈ«¶ÓÈ˵ÄÐÅϢ֪ͨ¸øÕâ¸öÈË
    #tagPlayerTeam.Sync_OtherTeamMemberInfoToCurPlayer(joinPlayer) # 09 14 ¿çµØÍ¼³ÉÔ±ÐÅÏ¢#tagTeamMemberState
    #֪ͨÕâ¸öÈ˵ÄÐÅÏ¢¸øÈ«¶Ó
    #joinPlayer.Sync_TeamMemberState() # 09 14 ¿çµØÍ¼³ÉÔ±ÐÅÏ¢#tagTeamMemberState
    #joinPlayer.NotifyCode("TeamOK")
    #teamPlayer.NotifyCode("TeamOK")
    
    #´¦ÀíÆ¥Åä
    if IsPlayerMatchingTeam(joinPlayer.GetPlayerID()):
        if isAutoMatchJoin:
            PlayerControl.NotifyCode(joinPlayer, "TeamMatchingSucceed")
        DelPlayerIDFromMatchingList(joinPlayer)
    if IsTeamMatchingPlayer(teamID):
        if tagTeam.IsTeamFull():
            if isAutoMatchJoin:
                PlayerControl.NotifyCode(teamPlayer, "TeamMatchingSucceed")
            DelTeamIDFromMatchingList(tagTeam)
        else:
            Sync_TeamMatchState(joinPlayer, True)
            
    __DoLogic_PlayerTeamChange(joinPlayer)
    return True
def __GetPlayerTeamLV(curPlayer):
    ##»ñµÃÍæ¼ÒÔÚ¶ÓÎéÖеÄȨÏ޵ȼ¶
    curTeam = curPlayer.GetTeam()
    if curTeam == None:
        return IPY_GameServer.tmlMember
    
    teamMember = curTeam.GetMemberByID(curPlayer.GetPlayerID())
    return teamMember.GetTeamLV()
def SyncMapServerTeamInfo(curTeam, eventName="", drDict={}):
    '''ͬ²½¶ÓÎéÐÅÏ¢µ½ MapServer ¸øËùÓÐÔÚÏß¶ÓÔ±
    @note: ÐèҪȫ¶Óͬ²½µÄÇé¿ö£º´´½¨¶ÓÎé¡¢¶ÓÔ±¼ÓÈë¡¢Í˳ö¡¢ÉÏÏß¡¢ÏÂÏß¡¢Çл»µØÍ¼¡¢VIPµÈ¼¶±ä¸ü¡¢VIPµ½ÆÚʱ¼ä¸üÐÂ
    '''
    if not curTeam:
        DR_Team("%s_Error" % eventName, 0, drDict)
        return
    teamID = curTeam.GetTeamID()
    syncPlayerList = []
    memInfoList = []
    memList = []
    for index in xrange(curTeam.GetMemberCount()):
        memPlayer = curTeam.GetMemberPlayer(index)
        memberInfo = curTeam.GetMemberInfo(index)
        if not memberInfo:
            memList.append(["not memberInfo"])
            continue
        if not memPlayer:
            memList.append(["not memPlayer"])
            continue
        memPlayerID = memPlayer.GetPlayerID()
        if not memPlayerID:
            memList.append(["not memPlayerID"])
            continue
        memInfo = ChGameToMapPyPack.tagGMTeamMemInfo()
        memInfo.PlayerID = memPlayerID
        memInfo.MapID = memPlayer.GetMapID()
        memInfo.VIPLV = PlayerControl.GetValidVIPLV(memPlayer)
        memInfoList.append(memInfo)
        syncPlayerList.append([memPlayer, memberInfo.GetTeamLV()])
        memList.append([memPlayerID, memPlayer.GetTeamID(), memberInfo.GetTeamLV(), memPlayer.GetMapID(), memPlayer.GetFBID()])
        
    for player, teamLV in syncPlayerList:
        teamInfo = ChGameToMapPyPack.tagGMTeamInfo()
        teamInfo.PlayerID = player.GetPlayerID()
        teamInfo.TeamID = teamID
        teamInfo.TeamLV = teamLV
        teamInfo.MemInfoList = memInfoList
        teamInfo.MemCnt = len(teamInfo.MemInfoList)
        NetPackCommon.SendPyPackToMapServer(player.GetLineNO(), player.GetRealMapID(), teamInfo)
        
    drDict.update({"MemList":memList})
    DR_Team(eventName, teamID, drDict)
    return
def SyncMapServerPlayerNoTeam(curPlayer):
    ## ͬ²½µØÍ¼Íæ¼ÒûÓжÓÎ飬ÇÐͼʱµ÷ÓÃ
    teamInfo = ChGameToMapPyPack.tagGMTeamInfo()
    teamInfo.PlayerID = curPlayer.GetPlayerID()
    teamInfo.TeamID = 0
    teamInfo.TeamLV = 0
    teamInfo.MemInfoList = []
    teamInfo.MemCnt = len(teamInfo.MemInfoList)
    NetPackCommon.SendPyPackToMapServer(curPlayer.GetLineNO(), curPlayer.GetRealMapID(), teamInfo)
    return
def SyncMapServerPlayerLeaveTeam(curPlayer, teamID):
    ## ͬ²½µØÍ¼Íæ¼ÒÀ뿪¶ÓÎé
    leavePack = ChGameToMapPyPack.tagGMPlayerLeaveTeam()
    leavePack.PlayerID = curPlayer.GetPlayerID()
    leavePack.CopyMapID = curPlayer.GetFBID()
    leavePack.TeamID = teamID
    NetPackCommon.SendPyPackToMapServer(curPlayer.GetLineNO(), curPlayer.GetRealMapID(), leavePack)
    return
#---------------------------------------------------------------------
#// B9 03 Ð޸ĶÓÎéÐÅÏ¢ #tagCGChangeTeamInfo
#
#struct    tagCGChangeTeamInfo
#{
#    tagHead        Head;
#    DWORD        TagMapID;    // Ä¿±êµØÍ¼
#    WORD        TagMapEx;    // Ä¿±êµØÍ¼À©Õ¹
#    WORD        ReqMinLV;    // ¶ÓÔ±×îµÍµÈ¼¶ÏÞÖÆ
#    WORD        ReqMaxLV;    // ¶ÓÔ±×î¸ßµÈ¼¶ÏÞÖÆ
#};
def OnChangeTeamInfo(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    tagMapID = clientData.TagMapID
    tagMapEx = clientData.TagMapEx
    reqMinLV = clientData.ReqMinLV
    reqMaxLV = clientData.ReqMaxLV
    
    DoChangeTeamTagMap(curPlayer, curPlayer.GetTeam(), tagMapID, tagMapEx, reqMinLV, reqMaxLV)
    return
def DoChangeTeamTagMap(curPlayer, curTeam, tagMapID=0, tagMapEx=0, reqMinLV=1, reqMaxLV=0):
    playerID = 0 if not curPlayer else curPlayer.GetPlayerID()
    #curTeam = curPlayer.GetTeam()
    if curTeam == None:
        GameWorld.DebugLog("Íæ¼ÒûÓжÓÎ飬ÎÞ·¨Ð޸ĶÓÎéÐÅÏ¢£¡", playerID)
        return
    
    #Ñé֤ȨÏÞ
    if curPlayer:
        curPlayerTeamLv = __GetPlayerTeamLV(curPlayer)
        if curPlayerTeamLv != IPY_GameServer.tmlLeader :
            GameWorld.ErrLog("²»ÊǶӳ¤£¬ÎÞ·¨Ð޸ĶÓÎéÄ¿±ê! curPlayerTeamLv=%s" % (curPlayerTeamLv), playerID)
            return
    
    teamID = curTeam.GetTeamID()
    #¶ÓÎé×Ô¶¯Æ¥ÅäÖУ¬ÎÞ·¨±ä¸ü¶ÓÎéÐÅÏ¢
    if IsTeamMatchingPlayer(teamID):
        GameWorld.Log("¶ÓÎé×Ô¶¯Æ¥ÅäÖУ¬ÎÞ·¨±ä¸ü¶ÓÎéÐÅÏ¢!teamID=%s" % teamID, playerID)
        return
    
    if tagMapID and not GameWorld.GetMap(tagMapID):
        GameWorld.ErrLog("Ä¿±êµØÍ¼²»´æÔÚ£¬ÎÞ·¨±ä¸ü¶ÓÎéÐÅÏ¢!tagMapID=%s" % tagMapID, playerID)
        return
    
    if not reqMaxLV:
        reqMaxLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV")
        
    curTeam.SetTagMapID(tagMapID)
    curTeam.SetTagMapEx(tagMapEx)
    curTeam.SetReqMinLV(reqMinLV)
    curTeam.SetReqMaxLV(reqMaxLV)
    GameWorld.DebugLog("Ð޸ĶÓÎéÐÅÏ¢: teamID=%s,tagMapID=%s,mapEx=%s,reqLV(%s~%s)" 
                       % (teamID, tagMapID, tagMapEx, reqMinLV, reqMaxLV), playerID)
    if tagMapID:
        UpdateTeamTagMapTime(teamID, tagMapID, True)
    #UpdSceneTeamVersion(curPlayer.GetMapID(), tick)
    
    #֪ͨ¿Í»§¶Ë
    teamInfoChange = ChPyNetSendPack.tagGCTeamInfoChange()
    teamInfoChange.TagMapID = tagMapID
    teamInfoChange.TagMapEx = tagMapEx
    teamInfoChange.ReqMinLV = reqMinLV
    teamInfoChange.ReqMaxLV = reqMaxLV
    SendTeamFakePack(curTeam, teamInfoChange)
    
    # ÐÞ¸ÄÄ¿±êµØÍ¼¶ÓÎéID×Öµä, ÏÈÒÆ³ý£¬ÔÙÌí¼Ó
    DelTeamIDFromTagMapTeamDict(teamID)
    AddTeamIDToTagMapTeamDict(teamID, tagMapID)
    return True
def SendTeamFakePack(curTeam, sendPack, ignorePlayerID=0):
    for i in xrange(curTeam.GetMemberCount()):
        memberInfo = curTeam.GetMemberInfo(i)
        playerID = memberInfo.GetPlayerID()
        if not playerID or playerID == ignorePlayerID:
            continue
        memberPlayer = curTeam.GetMemberPlayer(i)
        if not memberPlayer:
            continue
        if not memberPlayer.GetPlayerID():
            continue
        
        if PlayerControl.GetIsTJG(memberPlayer):
            continue
        
        NetPackCommon.SendFakePack(memberPlayer, sendPack)
    return
    
#===============================================================================
# //09 02 ¶Ó³¤Ìß³öÍæ¼Ò#tagCLeaderKickPlayer
# tagCLeaderKickPlayer       *   GettagCLeaderKickPlayer();
# 
# class   IPY_CLeaderKickPlayer
# {
# public:
# 
#    int      GetPlayerID();
# };
#===============================================================================
##¶Ó³¤Ìß³öÍæ¼Ò
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //09 02 ¶Ó³¤Ìß³öÍæ¼Ò#tagCLeaderKickPlayer
def LeaderKickPlayer(index, tick):
    #»ñµÃ·â°ü
    sendPack = IPY_GameServer.IPY_CLeaderKickPlayer()
    #ÒªÌß³öµÄÍæ¼ÒID
    tagPlayerID = sendPack.GetPlayerID()
    __Func_LeaderKickPlayer(index, tagPlayerID, tick)
    return
def __Func_LeaderKickPlayer(index, tagPlayerID, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curPlayerID = curPlayer.GetID()
    
    #»ñµÃ¶ÓÎé
    curTeam = curPlayer.GetTeam()
    
    if curTeam == None:
        GameWorld.ErrLog('¶Ó³¤Ìß³öÍæ¼Ò, Íæ¼ÒÎÞ¶ÓÎé, ÎÞ·¨ÌßÈË£¡', curPlayerID)
        return
    
    #---ÑéÖ¤³ÉÔ±ÊôÐÔ---
    curMember = curTeam.GetMemberByID(tagPlayerID)
    
    if curMember == None:
        GameWorld.ErrLog('¶Ó³¤Ìß³öÍæ¼Ò, ¶ÓÎéÎÞ´ËÍæ¼Ò = %s' % (tagPlayerID), curPlayerID)
        return
    
    #²»ÔÊÐíÌß³ö×Ô¼º
    if curPlayerID == tagPlayerID:
        return
    
    #Ñé֤ȨÏÞ
    curPlayerTeamLv = __GetPlayerTeamLV(curPlayer)
    
    if curPlayerTeamLv != IPY_GameServer.tmlLeader:
        GameWorld.ErrLog('²»ÊǶӳ¤£¬ÎÞ·¨Ìß³öÍæ¼Ò£¡ curPlayerTeamLv = %s' % (curPlayerTeamLv), curPlayerID)
        return
    
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
    if not __CheckCanTeamComm(curPlayer, tagPlayer):
        return
    
    #---Ìß³öÍæ¼Ò, ÔÊÐíÌß³ö²»ÔÚÏßµÄÍæ¼Ò---
    
    #LeaveProcession <%S%>À뿪Á˶ÓÎ飡
    #PlayerControl.NotifyCode(curTeam, "LeaveProcession", [curMember.GetPlayerName()])
    
    #---ÌßÈ˳ɹ¦, Ñé֤ʣÓà¶ÓÎéÇé¿ö---
    curTeamID = curTeam.GetTeamID()
    
    #µ±Ç°ÒѾÊǶÓÎé×îСÈËÊýÅäÖã¬ÌßÈ˺ó, ½âÉ¢µ±Ç°¶ÓÎé
    if curTeam.GetTeamPlayerCount() <= ChConfig.Def_Team_MinPlayerCount:
        GameWorld.DebugLog("¶Ó³¤Ìß³öÍæ¼Òºó, Òò¶ÓÎéÈËÊý²»×㣬×Ô¶¯½âÉ¢, ¶ÓÎéID = %s" % (curTeamID), curPlayerID)
        DoDismissTeam(curTeam)
        return
    
    #Ê£ÓàÈËÊýÂú×ã¶ÓÎé×îµÍÈËÊýÒªÇó
    GameWorld.Log('Ìß³öÍæ¼Ò³É¹¦£¡teamID=%s, tagPlayerID=%s' % (curTeamID, tagPlayerID), curPlayerID)
    
    __DoLogic_PlayerLeaveTeam(tagPlayer, tagPlayerID, curTeam, ChConfig.Def_Team_Sync_LeaveMsg_OtherKick, tick)
    
    #ÍÑ»úÍæ¼Ò±»Ìߣ¬Ôò¼Ç¼
    if tagPlayer and PlayerControl.GetIsTJG(tagPlayer):
        kickTeamIDList = PyGameData.g_tjgKickPlayerTeamDict.get(tagPlayerID, [])
        if curTeamID not in kickTeamIDList:
            kickTeamIDList.append(curTeamID)
            PyGameData.g_tjgKickPlayerTeamDict[tagPlayerID] = kickTeamIDList
    return
#---------------------------------------------------------------------
def __SetTeamLV(curTeamMember, teamLV, isNotify=True):
    '''ÉèÖóÉÔ±¶ÓÎéµÈ¼¶
     @param curTeamMember ¶ÓԱʵÀý
     @param teamLV ¶ÓÎéȨÏ޵ȼ¶
     @param isNotify ÊÇ·ñ¹ã²¥¶ÓÔ±
    '''
    curTeamMember.SetTeamLV(teamLV)
    tagPlayer = curTeamMember.GetPlayer()
    
    if tagPlayer == None:
        return
    
    #if notifyMapServer:
    #    tagPlayer.MapServer_Sync_Team(teamLV)
    
    if isNotify:
        if teamLV == IPY_GameServer.tmlLeader:
            #{%S1%}³ÉΪÁËеĶӳ¤!
            PlayerControl.NotifyCode(tagPlayer.GetTeam(), "InsteadHeader", [tagPlayer.GetName()])
            
        elif teamLV == IPY_GameServer.tmlMemberCanCall:
            #{%S1%}±»¶Ó³¤¸³ÓèÁËÕÐÈËȨÏÞ!
            # EndowPopedom ¸ÄΪ GeRen_chenxin_76326
            PlayerControl.NotifyCode(tagPlayer.GetTeam(), "GeRen_chenxin_76326", [tagPlayer.GetName()])
            
        elif teamLV == IPY_GameServer.tmlMember:
            #֪ͨ:{%S1%}±»¶Ó³¤ÊÕ»ØÁËÕÐÈËȨÏÞ
            PlayerControl.NotifyCode(tagPlayer.GetTeam(), "WithdrawalPopedom", [tagPlayer.GetName()])
            
    return
#---------------------------------------------------------------------
#===============================================================================
# //09 06 ¶Ó³¤¸³Óè¶ÓԱȨÏÞ/½»¸¶¶Ó³¤ #tagCTeamChangeMemberState
# tagCTeamChangeMemberState   * GettagCTeamChangeMemberState();
# class  IPY_CTeamChangeMemberState
# {
# public:
# //Ä¿±êÍæ¼Ò
# int GetPlayerID();
# //Íæ¼Ò¶ÓÎéµÈ¼¶TTeamMemberLV
# int GetMemberLV();
# };
#===============================================================================
##¶Ó³¤¸ø¶ÓԱȨÏÞ.
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //09 06 ¶Ó³¤¸³Óè¶ÓԱȨÏÞ/½»¸¶¶Ó³¤ #tagCTeamChangeMemberState
def TeamChangeMemberState(index, tick):    
    #»ñµÃ·â°ü
    sendPack = IPY_GameServer.IPY_CTeamChangeMemberState() 
    tagPlayerID = sendPack.GetPlayerID()
    memberLV = sendPack.GetMemberLV()
    __Func_TeamChangeMemberState(index, tagPlayerID, memberLV, tick)
    return
def __Func_TeamChangeMemberState(index, tagPlayerID, memberLV, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curPlayerID = curPlayer.GetID()
    
    #---ÑéÖ¤Ìõ¼þ---
    
    #²»ÄÜ×Ô¼º¸ø×Ô¼ºÈ¨ÏÞ
    if curPlayerID == tagPlayerID:
        return
    
    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
    
    if tagPlayer == None:
        PlayerControl.NotifyCode(curPlayer, "Team_Header_TransferLost")
        return
    
    curTeam = curPlayer.GetTeam()
    if not curTeam:
        GameWorld.ErrLog("¶Ó³¤¸ø¶ÓԱȨÏÞ,Íæ¼ÒÎÞ¶ÓÎé", curPlayerID)
        return
    
    #Ñé֤ȨÏÞ
    curPlayerTeamLv = __GetPlayerTeamLV(curPlayer)
    if curPlayerTeamLv != IPY_GameServer.tmlLeader:
        GameWorld.ErrLog("¶Ó³¤¸ø¶ÓԱȨÏÞ, Íæ¼Ò·Ç¶Ó³¤£¬È¨Ï޵ȼ¶²»×ã! curPlayerTeamLv=%s" % (curPlayerTeamLv), curPlayerID)
        return
    
    if not __CheckCanTeamComm(curPlayer, tagPlayer):
        return
    
    #»ñÈ¡¶ÓÔ±
    packMember = curTeam.GetMemberByID(tagPlayerID)
    if packMember == None:
        GameWorld.ErrLog("¶Ó³¤¸ø¶ÓԱȨÏÞ, ¶ÓÔ±²»ÔڸöÓÎ飡 tagPlayerID=%s" % (tagPlayerID), curPlayerID)
        return
    
    teamID = curTeam.GetTeamID()
    
    #---Ñé֤ͨ¹ý, ¸øÈ¨ÏÞ---
    #¸ø¶Ó³¤(½«¶ÓÔ±ÉèÖÃΪ¶Ó³¤, ¶Ó³¤±ØÐëÏȽµ¼¶, ±ÜÃâÒ»¸ö¶ÓÎéÓÐ2¸ö¶Ó³¤)
    if memberLV == IPY_GameServer.tmlLeader:
        leadMember = curTeam.GetMemberByID(curPlayerID)
        __SetTeamLV(leadMember, IPY_GameServer.tmlMember, False)
        __SetTeamLV(packMember, IPY_GameServer.tmlLeader)
        
        # ÒÆ³ý¾É¶Ó³¤ËùÔÚ³¡¾°¶ÓÎ飬Ìí¼Óжӳ¤ËùÔÚ³¡¾°
        DelTeamIDFromSceneList(teamID, tick)
        AddTeamIDToSceneList(teamID, tagPlayer.GetMapID(), tick)
    
    #¸øÕÐÈËȨÏÞ
    elif memberLV == IPY_GameServer.tmlMemberCanCall:
        #½«¶ÓÔ±ÉèÖÃΪӵÓÐÕÐÈËȨÏÞ
        __SetTeamLV(packMember, memberLV)
        #GeRen_chenxin_612029  ÄúÓÐÁËÕÐÊÕжÓÎé³ÉÔ±µÄȨÀû£¡
        PlayerControl.NotifyCode(tagPlayer, "GeRen_chenxin_612029")
    #¸øÆÕͨ¶ÓԱȨÏÞ
    else:
        __SetTeamLV(packMember, IPY_GameServer.tmlMember)
        
    #֪ͨ¿Í»§¶Ë¶ÓÎé³ÉÔ±ÊôÐÔ±ä¸ü
    #curTeam.Sync_TeamState()
    Sync_TeamMemberInfo(curTeam)
    SyncMapServerTeamInfo(curTeam, "ChangeMemTeamLV", {"tagPlayerID":tagPlayerID, "memberLV":memberLV})
    return
#---------------------------------------------------------------------
#===============================================================================
# //09 07 À뿪¶ÓÎé#tagCLeaveTeam
# static          tagCLeaveTeam       g_tagCLeaveTeam;
# 
# tagCLeaveTeam       *   GettagCLeaveTeam()
# {
#    return  &g_tagCLeaveTeam;
# }
# 
# int      IPY_CLeaveTeam::GetType()
# {
#    return  GettagCLeaveTeam()->Type;
# }
#===============================================================================
##À뿪¶ÓÎé
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks //09 07 À뿪¶ÓÎé#tagCLeaveTeam 
def LeaveTeam(index, tick):
    #µ±Ç°Íæ¼Ò
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    #µ±Ç°Íæ¼ÒID
    curPlayerID = curPlayer.GetID()
    
    #ÊÇ·ñÓжÓÎé
    curTeam = curPlayer.GetTeam()
    
    if curTeam == None:
        GameWorld.ErrLog("À뿪¶ÓÎéÒì³£, Íæ¼ÒÎÞ¶ÓÎé", curPlayerID)
        return
    
    if not __CheckCanTeamComm(curPlayer):
        return
    
    DoPlayerLeaveTeam(curPlayer, curTeam, tick)
    return
def DoPlayerLeaveTeam(curPlayer, curTeam, tick):
    #µ±Ç°Íæ¼ÒID
    curPlayerID = curPlayer.GetID()
    teamID = curTeam.GetTeamID()
    
    #---¶ÓÎéÈËÊý²»×ã---
    
    #µ±Ç°ÒѾÊǶÓÎé×îСÈËÊýÅäÖã¬ÌßÈ˺ó, ½âÉ¢µ±Ç°¶ÓÎé
    if curTeam.GetTeamPlayerCount() <= ChConfig.Def_Team_MinPlayerCount:
        GameWorld.DebugLog("À뿪¶ÓÎ飬Òò¶ÓÎéÈËÊý²»×㣬½âÉ¢¶ÓÎé teamID= %s" % (teamID), curPlayerID)
        DoDismissTeam(curTeam)
        return
    
    #---¶ÓÎ黹ÄܳÉÁ¢---
    GameWorld.DebugLog("Íæ¼ÒÀ뿪¶ÓÎé: teamID=%s" % teamID, curPlayerID)
    
    #»ñµÃÍæ¼ÒÔÚ¶ÓÎéÖеÄʵÀý
    teamMember = curTeam.GetMemberByID(curPlayerID)
    
    #¶Ó³¤Àë¶Ó, ֪ͨ¶ÓԱеĶӳ¤ÉÏÈÎË¢ÐÂ
    if teamMember.GetTeamLV() == IPY_GameServer.tmlLeader :
        #¶Ó³¤Àë¶Ó, ÏÈÉèÖÃΪÆÕͨ¶ÓÔ±, ±ÜÃâ½»½Óºó, ÓÐ2¸ö¶Ó³¤
        __SetTeamLV(teamMember, IPY_GameServer.tmlMember, False)
        
        newLeader = __DoSetNewLeader(curTeam, curPlayerID)
        if newLeader:
            DelTeamIDFromSceneList(teamID, tick)
            AddTeamIDToSceneList(teamID, newLeader.GetMapID(), tick)
        
    #Àë¶ÓϵͳÌáʾ
    #LeaveProcession <%S%>À뿪Á˶ÓÎ飡
    #PlayerControl.NotifyCode(curTeam, "LeaveProcession", [curPlayer.GetName()])
    
    #AlreadyLeave to GeRen_chenxin_498155
    #GeRen_chenxin_498155   ÄúÒѾÀ뿪Á˶ÓÎ飡
    PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_498155")
    #À뿪¶ÓÎé
    __DoLogic_PlayerLeaveTeam(curPlayer, curPlayer.GetID(), curTeam, ChConfig.Def_Team_Sync_LeaveMsg_Self, tick)
    return
def __DoSetNewLeader(curTeam, oldLeaderID):
    '''ÓÉÓÚijЩÔÒòÐèÒª×ªÒÆ¶Ó³¤£¬Èç¶Ó³¤ÏÂÏß¡¢¶Ó³¤Àë¶ÓµÈ
        ĿǰĬÈÏ×ªÒÆ¸øÔÚÏßµÄÏÂÒ»Ãû¶ÓÔ±
        @return: жӳ¤playerʵÀý
    '''
    
    for i in xrange(curTeam.GetMemberCount()):
        curMemberPlayer = curTeam.GetMemberPlayer(i)
        curMemberInfo = curTeam.GetMemberInfo(i)
        #¹ýÂ˲»ÔÚÏߵijÉÔ±
        if curMemberPlayer == None or curMemberPlayer.GetPlayerID() == 0:
            continue
        
        #¹ýÂË֮ǰµÄ¶Ó³¤
        if curMemberInfo.GetPlayerID() == oldLeaderID:
            continue
        
        #ÉèÖÃжӳ¤, ÔÚÕâ¸öÀïÃæ»á֪ͨMapServer
        __SetTeamLV(curMemberInfo, IPY_GameServer.tmlLeader)
        GameWorld.DebugLog("ϵͳÉèÖöÓÎéжӳ¤: teamID=%s,oldLeaderID=%s,newLeaderID=%s" 
                           % (curTeam.GetTeamID(), curMemberPlayer.GetPlayerID(), oldLeaderID))
        return curMemberPlayer
    return
#---------------------------------------------------------------------
def __DoLogic_PlayerLeaveTeam(delPlayer, delPlayerID, curTeam, msg, tick):
    ##ÔÚÏßÍæ¼ÒÀë¶Ó
    # @param delPlayer ɾ³ýÍæ¼ÒʵÀý(ÓпÉÄÜΪ¿Õ)
    # @param delPlayerID ɾ³ýÍæ¼ÒID
    # @param curTeam ¶ÓÎéʵÀý
    # @param msg ×Ô¼ºÀ뿪Ϊ0, ±»ÈËÌß³öΪ1
    # @return ·µ»ØÖµÎÞÒâÒå
    # @remarks ÔÚÏßÍæ¼ÒÀë¶Ó
    #֪ͨ¿Í»§¶Ë, Õâ¸ö±ØÐëÏÈ֪ͨ
    
    curTeam.Sync_LeaveTeam(delPlayerID, msg) # //09 06 Íæ¼ÒÀ뿪¶ÓÎéµÄÏûÏ¢#tagPlayerLeaveTeamMsg
    
    #GameServerɾ³ý¶ÓÔ±
    curTeam.DeleteMember(delPlayerID)
    
    #leaderPlayer = GetTeamLeader(curTeam)
    #UpdSceneTeamVersion(leaderPlayer.GetMapID(), tick)
    
    #ÒÔÏÂÂß¼Ö»¶ÔÔÚÏßÍæ¼Ò´¦Àí
    if delPlayer != None:
        SetTeamMemberPrepareState(delPlayer, TeamMemPrepareState_LeaveTeam, tick)
        #GameServerÇå³ýÍæ¼Ò¶ÓÎéIDΪ¿Õ
        delPlayer.SetTeam(None)
        #֪ͨMapServerd¶ÓÎé±ä¸ü, ÔÚmapserver¹¹½¨Ä¿Ç°¶ÓÎé
        #delPlayer.MapServer_Sync_Team(0)
        SyncMapServerPlayerLeaveTeam(delPlayer, curTeam.GetTeamID())
        #Íæ¼ÒÀ뿪¸±±¾
        delPlayer.MapServer_LeaveFB()
        if IsTeamMatchingPlayer(curTeam.GetTeamID()):
            Sync_TeamMatchState(delPlayer, False)
        __DoLogic_PlayerTeamChange(delPlayer)
            
    #¹ã²¥¶ÓÎéË¢ÐÂ
    #curTeam.Sync_TeamState()
    Sync_TeamMemberInfo(curTeam)
    SyncMapServerTeamInfo(curTeam, "Leave", {"delPlayerID":delPlayerID, "msg":msg})
    
    #ÎÞÈËÔÚÏß
    if curTeam.GetTeamPlayerCount() <= 0:
        isTeamEmpty = True
        for i in xrange(curTeam.GetMemberCount()):
            memberInfo = curTeam.GetMemberInfo(i)
            if memberInfo.GetPlayerID():
                isTeamEmpty = False
                break
        if isTeamEmpty:
            # ¶ÓÎéΪ¿Õ£¬ËµÃ÷ËùÓжÓÔ±¶¼ÏÂÏß³¬¹ýÀë¶Ó±£»¤Ê±¼äÁË£¬¶ÓÎé¿É½âɢɾ³ý
            #GameWorld.DebugLog("Íæ¼ÒÀë¶Óºó£¬ÎÞ¶ÓÔ±ÔÚÏßÇÒ¶ÓÎéΪ¿Õ£¬Ôòɾ³ý¶ÓÎ飡teamID=%s" % curTeam.GetTeamID())
            DeleteTeam(curTeam, tick)
    return
def __DoLogic_PlayerTeamChange(curPlayer):
    '''Íæ¼Ò¶ÓÎé±ä¸üͨÓô¦Àí£¬ Í˳öºÍ¼ÓÈëµÄͳһÂß¼
    '''
    #GameWorld.DebugLog("Íæ¼Ò¶ÓÎé±ä¸üͨÓô¦Àí,curTeamID=%s" % curPlayer.GetTeamID())
    GameWorldBoss.OnPlayerTeamChange(curPlayer)
    return
#---------------------------------------------------------------------
def DoDismissTeam(curTeam):
    ##½âÉ¢¶ÓÎé
    
    if not curTeam:
        return
    
    for i in xrange(curTeam.GetMemberCount()):
        curMember = curTeam.GetMemberInfo(i)
        curPlayer = curMember.GetPlayer()
        #²»ÔÚÏßÍæ¼Ò
        if curPlayer == None:
            continue
        
        #AlreadyLeave to GeRen_chenxin_498155
        #ϵͳÌáʾ, GeRen_chenxin_498155 ÄãÒѾÀ뿪Á˶ÓÎé!
        PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_498155")
        
        #GameServerÍæ¼Ò¶ÓÎéΪ¿Õ
        curPlayer.SetTeam(None)
        #֪ͨMapServerd¶ÓÎé±ä¸ü
        #curPlayer.MapServer_Sync_Team(0)
        SyncMapServerPlayerLeaveTeam(curPlayer, curTeam.GetTeamID())
        __DoLogic_PlayerTeamChange(curPlayer)
        if curMember.GetTeamLV() != IPY_GameServer.tmlLeader:
            #·Ç¶Ó³¤ÈËԱȫ²¿À뿪¸±±¾
            curPlayer.MapServer_LeaveFB()
    #ɾ³ý¶ÓÎé
    DeleteTeam(curTeam, GameWorld.GetGameWorld().GetTick())
    return True
def DeleteTeam(curTeam, tick):
    teamID = curTeam.GetTeamID()
    DelTeamIDFromSceneList(teamID, tick)
    DelTeamIDFromTagMapTeamDict(teamID)
    DelTeamIDFromMatchingList(curTeam)
    if teamID in PyGameData.g_teamFBEnterAskDict:
        PyGameData.g_teamFBEnterAskDict.pop(teamID)
    if teamID in PyGameData.g_prepareTeamDict:
        PyGameData.g_prepareTeamDict.pop(teamID)
    #Õâ¾ä»°ÖÐ, »áÇå³ýËùÓжÓÎé³ÉÔ±, ɾ³ýË÷Òý
    #ËùÒÔ±ØÐë·ÅÔÚ×îºóÒ»¾ä
    #2009.10.10
    #bug:
    #Sync_DismissTeam »áÇå¿ÕTeamID, µ¼ÖÂɾ³ý²»Á˶ÓÎé
    curTeam.Sync_DismissTeam() # //09 05 ½âÉ¢¶ÓÎé#tagTeamClear
    GameWorld.GetTeamManager().DeleteTeam(teamID) # ×îºóÕæÊµÉ¾³ý¶ÓÎéID
    return
#---------------------------------------------------------------------
#===============================================================================
# //09 08 ½âÉ¢¶ÓÎé#tagCDismissTeam
# static          tagCDismissTeam       g_tagCDismissTeam;
# 
# tagCDismissTeam       *   GettagCDismissTeam()
# {
#    return  &g_tagCDismissTeam;
# }
# 
# int      IPY_CDismissTeam::GetType()
# {
#    return  GettagCDismissTeam()->Type;
# }
#===============================================================================
##½âÉ¢¶ÓÎé.
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //09 08 ½âÉ¢¶ÓÎé#tagCDismissTeam
def DismissTeam(index, tick):
    GameWorld.GetPsycoFunc(__Func_DismissTeam)(index, tick)
    return
def __Func_DismissTeam(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curPlayerID = curPlayer.GetID()
    
    curTeam = curPlayer.GetTeam()
    
    if curTeam == None:
        GameWorld.DebugLog('½âÉ¢¶ÓÎéÒì³£, Íæ¼ÒÎÞ¶ÓÎé', curPlayerID)
        return
    #Ñé֤ȨÏÞ
    curPlayerTeamLv = __GetPlayerTeamLV(curPlayer)
    
    if curPlayerTeamLv != IPY_GameServer.tmlLeader :
        GameWorld.DebugLog("½âÉ¢¶ÓÎéÒì³£, ²»ÊǶӳ¤£¬ÎÞ·¨½âÉ¢£¡curPlayerTeamLv=%s" % (curPlayerTeamLv), curPlayerID)
        return
    
    if not __CheckCanTeamComm(curPlayer):
        return
    
    #½âÉ¢¶ÓÎé
    DoDismissTeam(curTeam)
    return
#---------------------------------------------------------------------
def GetTeamLeader(destTeam):
    ##»ñµÃ¶Ó³¤ÊµÀý
    
    for index in xrange(destTeam.GetMemberCount()):
        curMember = destTeam.GetMemberPlayer(index)
        if not curMember or not curMember.GetPlayerID():
            continue
        
        curMemberInfo = destTeam.GetMemberInfo(index)
        if curMemberInfo.GetTeamLV() != IPY_GameServer.tmlLeader:
            continue
        
        return curMemberInfo.GetPlayer()
    
    return None
def CheckTeamLV(curPlayer):
    ##¼ì²é¶ÓÎéÊÇ·ñÓÐÊÕÈËȨÏÞ
    teamLV = __GetPlayerTeamLV(curPlayer)
    return (teamLV == IPY_GameServer.tmlMemberCanCall or 
             teamLV == IPY_GameServer.tmlLeader)
    
def CheckTeamOnLineCount(curTeam):
    ##»ñµÃ¶ÓÎéÊ£ÓàÔÚÏßÈËÊý
    
    count = 0
    for i in xrange(curTeam.GetMemberCount()):
        curPlayer = curTeam.GetMemberPlayer(i)
        if curPlayer == None:
            continue
        count += 1
    return count
#===============================================================================
#// B9 05 ²éÑ¯ÍÆ¼ö×é¶ÓµÄ¸½½üÍæ¼Ò #tagCGQueryRecommendNearbyPlayer
#
#struct    tagCGQueryRecommendNearbyPlayer
#{
#    tagHead        Head;
#};
def OnQueryRecommendNearbyPlayer(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    if not GameWorld.RefurbishPlayerTick(curPlayer, ChConfig.TYPE_Player_Tick_QueryRecommendNearbyKey, tick):
        GameWorld.DebugLog("¸½½üÍæ¼Ò²éѯ¼ä¸ôδµ½...")
        return
    
    mapID = curPlayer.GetMapID()
    curPlayerID = curPlayer.GetPlayerID()
    
    Def_SyncPlayerCount = 20 # ͬ²½¸ø¿Í»§¶ËµÄ¶ÓÎéÊý, ÕâÀïÔÝÓɳÌÐò¿ØÖÆÐ´ËÀ
    
    playerMgr = GameWorld.GetPlayerManager()
    
    scenePlayerIDDict = GetScenePlayerIDDict()
    scenePlayerIDList = copy.deepcopy(scenePlayerIDDict.get(mapID, []))
    # ³¡¾°¶ÓÎéÊý³¬¹ýͬ²½µÄ¸öÊý²Å½øÐÐÅÅÐò£¬·ñÔòÖ±½Óͬ²½¸ø¿Í»§¶Ë£¬Óɿͻ§¶Ë×ÔÐÐÅÅÐò
    if len(scenePlayerIDList) > Def_SyncPlayerCount:
        playerIDSortList = []
        curPlayerLV = curPlayer.GetLV()
        for playerID in scenePlayerIDList:
            if playerID == curPlayerID:
                continue
            player = playerMgr.FindPlayerByID(playerID)
            if not player:
                continue
            if PlayerControl.GetIsTJG(player):
                continue
            if not __CheckCanTeamComm(player):
                continue
            #if player.GetTeamID():
            #    # ÓжÓÎéµÄ²»ÍƼö
            #    continue
            playerLV = player.GetLV()
            playerIDSortList.append([abs(curPlayerLV - playerLV), -playerLV, playerID])
        playerIDSortList.sort() # µÈ¼¶²î¾ø¶ÔÖµÉýÐòÅÅ£¬ ¾ø¶ÔÖµÏàͬµÄµÈ¼¶¸ßµÄÅÅÇ°Ãæ
        scenePlayerIDList = [teamInfo[2] for teamInfo in playerIDSortList]
    
    # ͬ²½¿Í»§¶Ë
    nearbyPlayerInfo = ChPyNetSendPack.tagGCRecommendNearbyPlayerList()
    nearbyPlayerInfo.PlayerList = []
    count = 0
    for playerID in scenePlayerIDList:
        if count >= Def_SyncPlayerCount:
            break
        if playerID == curPlayerID:
            continue
        player = playerMgr.FindPlayerByID(playerID)
        if not player:
            continue
        if PlayerControl.GetIsTJG(player):
            continue
        if not __CheckCanTeamComm(player):
            continue
        #if player.GetTeamID():
        #    # ÓжÓÎéµÄ²»ÍƼö
        #    continue
        count += 1
        nearbyPlayer = ChPyNetSendPack.tagGCRecommendNearbyPlayer()
        nearbyPlayer.PlayerID = playerID
        nearbyPlayer.Name = player.GetName()
        nearbyPlayer.NameLen = len(nearbyPlayer.Name)
        nearbyPlayer.LV = player.GetLV()
        nearbyPlayer.Job = player.GetJob()
        nearbyPlayer.JobLevel = PlayerControl.GetJobRank(player)
        nearbyPlayer.RealmLV = player.GetOfficialRank()
        nearbyPlayerInfo.PlayerList.append(nearbyPlayer)
        
    playerCount = len(nearbyPlayerInfo.PlayerList)
    nearbyPlayerInfo.PlayerCount = playerCount
    NetPackCommon.SendFakePack(curPlayer, nearbyPlayerInfo)
    GameWorld.DebugLog("ͬ²½¸ø¿Í»§¶Ë³¡¾°¸½½üÍæ¼ÒÊý: mapID=%s,playerCount=%s,scenePlayerIDList=%s" 
                       % (mapID, playerCount, scenePlayerIDList), curPlayerID)
    return
# //09 0Bˢг¡¾°¶ÓÎé#tagCRefreshSceneTeam
# //ÐèÒª·þÎñ¶Ë»ØÓ¦¶ÔÐÔÄÜÒª±È½Ï´óµÄÓ°Ïì
# structtagCRefreshSceneTeam
# {
#    tagHead Head;
# };
#===============================================================================
##×é¶Ó²éѯ.
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦
def RefreshSceneTeam(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    
    if not GameWorld.RefurbishPlayerTick(curPlayer, ChConfig.TYPE_Player_Tick_QueryTeamInfoKey, tick):
        GameWorld.DebugLog("ˢг¡¾°¶ÓÎéʱ¼ä¼ä¸ôδµ½...")
        return
    
    #curTeamID = curPlayer.GetTeamID()
    mapID = curPlayer.GetMapID()
    playerID = curPlayer.GetPlayerID()
    #ÔÝʱ²»×ö²éѯ°æ±¾ÏÞÖÆ
#    lastQueryVersionDict = PyGameData.g_sceneTeamQueryVersion.get(playerID, {})
#    lastQueryVersion = lastQueryVersionDict.get(mapID, -1)
#    sceneTeamVersion = PyGameData.g_sceneTeamServerVersion.get(mapID, 0)
#    if lastQueryVersion == sceneTeamVersion:
#        GameWorld.DebugLog("Íæ¼ÒÒÑ»ñµÃ·þÎñÆ÷×îг¡¾°¶ÓÎé°æ±¾!sceneTeamVersion=%s" % sceneTeamVersion, curPlayer.GetPlayerID())
#        return
#    lastQueryVersionDict[mapID] = sceneTeamVersion
#    PyGameData.g_sceneTeamQueryVersion[playerID] = lastQueryVersionDict
    
    Def_SyncTeamCount = 20 # ͬ²½¸ø¿Í»§¶ËµÄ¶ÓÎéÊý, ÕâÀïÔÝÓɳÌÐò¿ØÖÆÐ´ËÀ
    
    sceneTeamDict = GetSceneTeamIDDict()
    sceneTeamIDList = sceneTeamDict.get(mapID, [])
    teamMgr = GameWorld.GetTeamManager()
    # ³¡¾°¶ÓÎéÊý³¬¹ýͬ²½µÄ¸öÊý²Å½øÐÐÅÅÐò£¬·ñÔòÖ±½Óͬ²½¸ø¿Í»§¶Ë£¬Óɿͻ§¶Ë×ÔÐÐÅÅÐò
    if len(sceneTeamIDList) > Def_SyncTeamCount:
        fullTeamIDList = []
        otherTeamIDList = []
        for teamID in sceneTeamIDList:
            #if teamID == curTeamID: # ²»Í¬²½×Ô¼º¶ÓÎé
            #    continue
            team = teamMgr.FindTeam(teamID)
            if not team:
                continue
            memberCount = team.GetMemberCount()
            if memberCount >= ChConfig.Def_Team_MaxPlayerCount:
                fullTeamIDList.append([memberCount, teamID])
            else:
                otherTeamIDList.append([memberCount, teamID])
        otherTeamIDList.sort(reverse=True) # δÂúÔ±µÄ¶ÓÎéµ¹ÐòÅÅ
        sceneTeamIDSortList = otherTeamIDList + fullTeamIDList # δÂúÔ±µ¹ÐòÅÅ£¬ÂúÔ±µÄ²åÔÚ¶ÓÁкóÃæ
        sceneTeamIDList = [teamInfo[1] for teamInfo in sceneTeamIDSortList]
    
    # ͬ²½¿Í»§¶Ë
    sceneTeamInfo = ChPyNetSendPack.tagGCSceneTeamRefresh()
    sceneTeamInfo.SceneTeamList = []
    count = 0
    for teamID in sceneTeamIDList:
        if count >= Def_SyncTeamCount:
            break
        #if teamID == curTeamID: # ²»Í¬²½×Ô¼º¶ÓÎé
        #    continue
        team = teamMgr.FindTeam(teamID)
        if not team:
            continue
        leader = GetTeamLeader(team)
        if not leader:
            continue
        count += 1
        sceneTeam = ChPyNetSendPack.tagGCSceneTeam()
        sceneTeam.PlayerID = leader.GetPlayerID()
        sceneTeam.PlayerName = leader.GetName()
        sceneTeam.NameLen = len(sceneTeam.PlayerName)
        sceneTeam.LV = leader.GetLV()
        sceneTeam.Job = leader.GetJob()
        sceneTeam.JobLevel = PlayerControl.GetJobRank(leader)
        sceneTeam.RealmLV = leader.GetOfficialRank()
        sceneTeam.MemberCount = team.GetTeamPlayerCount()
        sceneTeam.TagMapID = team.GetTagMapID()
        sceneTeam.TagMapEx = team.GetTagMapEx()
        sceneTeam.ReqMinLV = team.GetReqMinLV()
        sceneTeam.ReqMaxLV = team.GetReqMaxLV()
        sceneTeamInfo.SceneTeamList.append(sceneTeam)
    teamCount = len(sceneTeamInfo.SceneTeamList)
    sceneTeamInfo.TeamCount = teamCount
    NetPackCommon.SendFakePack(curPlayer, sceneTeamInfo)
    GameWorld.DebugLog("ͬ²½¸ø¿Í»§¶Ë³¡¾°¶ÓÎéÊý: mapID=%s,teamCount=%s,sceneTeamIDList=%s" 
                       % (mapID, teamCount, sceneTeamIDList), playerID)
    return
#---------------------------------------------------------------------
def OnServerClose(tick):
    #GameWorld.DebugLog("¹Ø·þǰ¶ÓÎé´¦Àí£¡")
    teamMgr = GameWorld.GetTeamManager()
    for playerID, leaveTeamInfo in PyGameData.g_countdownLeaveTeamDict.items():
        teamID, leaveServerTick = leaveTeamInfo
        team = teamMgr.FindTeam(teamID)
        if team:
            #GameWorld.DebugLog("    ¹Ø·þÍæ¼ÒÇ¿ÖÆÀë¶Ó: playerID=%s,teamID=%s" % (playerID, teamID))
            __DoLogic_PlayerLeaveTeam(None, playerID, team, ChConfig.Def_Team_Sync_LeaveMsg_Self, tick)
            
    return
def DoCountdownLeaveTeamLogic(tick):
    ## ÏÂÏߺ󵹼ÆÊ±Àë¶Ó´¦Àí, ÿ·ÖÖÓ´¦ÀíÒ»´Î
    #GameWorld.DebugLog("ÏÂÏߺ󵹼ÆÊ±Àë¶Ó´¦Àí: %s" % PyGameData.g_countdownLeaveTeamDict)
    teamMgr = GameWorld.GetTeamManager()
    for playerID, leaveTeamInfo in PyGameData.g_countdownLeaveTeamDict.items():
        teamID, leaveServerTick = leaveTeamInfo
        if tick - leaveServerTick < ChConfig.Def_CountdownLeaveTeamTime:
            continue
        PyGameData.g_countdownLeaveTeamDict.pop(playerID)
        team = teamMgr.FindTeam(teamID)
        if team:
            #GameWorld.DebugLog("    Íæ¼ÒÏÂÏßʱ³¤³¬¹ýÀë¶Ó±£»¤Ê±¼ä£¬ÏµÍ³½«ÆäÀë¶Ó: playerID=%s,teamID=%s" % (playerID, teamID))
            __DoLogic_PlayerLeaveTeam(None, playerID, team, ChConfig.Def_Team_Sync_LeaveMsg_Self, tick)
            
    ResetTeamTagMapByTime()
    return
def DoPlayerLogOffTeamLogic(curPlayer, tick):
    ##×é¶ÓÍæ¼ÒÏÂÏßÂß¼
    
    playerID = curPlayer.GetPlayerID()
    DelPlayerIDFromSceneList(playerID)
    DelPlayerIDFromMatchingList(curPlayer)
    
    # ÒÆ³ýÌßÍÑ»úÍæ¼Ò¶ÓÎéÁбí
    if playerID in PyGameData.g_tjgKickPlayerTeamDict:
        PyGameData.g_tjgKickPlayerTeamDict.pop(playerID)
        
    curTeam = curPlayer.GetTeam()
    #ÎÞ¶ÓÎé
    if curTeam == None:
        return
    
    curTeamID = curPlayer.GetTeamID()
    mapID = curPlayer.GetMapID()
    isTJG = PlayerControl.GetIsTJG(curPlayer)
    
    GameWorld.DebugLog("Ö´ÐÐÍæ¼ÒÏÂÏß¶ÓÎéÂß¼!curTeamID=%s,isTJG=%s,mapID=%s,tick=%s" % (curTeamID, isTJG, mapID, tick), playerID)
    PyGameData.g_countdownLeaveTeamDict[playerID] = [curTeamID, tick]
    #GameWorld.DebugLog("    PyGameData.g_countdownLeaveTeamDict=%s" % PyGameData.g_countdownLeaveTeamDict)
    
    #===============================================================================================
    # if curTeam.GetTeamPlayerCount() <= 1:
    #    GameWorld.Log("Íæ¼ÒÏÂÏߣ¬¶ÓÎéÖ»ÓÐ×Ô¼ºÒ»ÈË£¬½âÉ¢¶ÓÎ飡", playerID)
    #    DoDismissTeam(curTeam)
    #    return
    #===============================================================================================
    if not PlayerControl.GetIsTJG(curPlayer):
        #¸æË߿ͻ§¶Ë¶ÓÎé³ÉÔ±ÏÂÏß
        curPlayer.Sync_TeamMemberDisconnect() # 09 12 ¶ÓÎé³ÉÔ±ÉÏÏß/ÏÂÏß#tagTeamMemberLoginInfo
    curTeamMember = curTeam.GetMemberByID(playerID)
    curTeamMember.SetPlayer(None)
    
    SetTeamMemberPrepareState(curPlayer, TeamMemPrepareState_Offline, tick)
    
    #¶Ó³¤ÏÂÏß
    if curTeamMember.GetTeamLV() == IPY_GameServer.tmlLeader:
        __SetTeamLV(curTeamMember, IPY_GameServer.tmlMember)
        
        newLeader = __DoSetNewLeader(curTeam, playerID)
        if newLeader:
            #newLeader.MapServer_Sync_Team(IPY_GameServer.tmlLeader)
            #curTeam.Sync_TeamState()
            DelTeamIDFromSceneList(curTeamID, tick)
            AddTeamIDToSceneList(curTeamID, newLeader.GetMapID(), tick)
            Sync_TeamMemberInfo(curTeam)
        else:
            DelTeamIDFromSceneList(curTeamID, GameWorld.GetGameWorld().GetTick())
            DelTeamIDFromTagMapTeamDict(curTeamID)
            DelTeamIDFromMatchingList(curTeam)
                
    SyncMapServerTeamInfo(curTeam, "LogOff", {"playerID":playerID})
    return
def OnPlayerLoginRefreshTeam(curPlayer, tick):
    ##Íæ¼ÒµÇ½ˢÐÂ×é¶Ó״̬
    # @remarks Íæ¼ÒµÇ¼ˢжÓÎé Íæ¼Ò¸ÕµÇ¼, ¾Í±ØÐëÒªSetTeam, ÒòΪÅж¨Íæ¼ÒÓÐûÓжÓÎé, ÊÇÓÃGetTeamÅж¨µÄ
    
    playerID = curPlayer.GetPlayerID()
    curTeamID = curPlayer.GetTeamID()
    GameWorld.DebugLog("Ö´ÐÐÍæ¼ÒÉÏÏß¶ÓÎéÂß¼!curTeamID=%s" % curTeamID, playerID)
    AddPlayerIDToSceneList(playerID, curPlayer.GetMapID())
    
    # ÒÆ³öÏÂÏßÑÓ³ÙÀë¶Ó
    if playerID in PyGameData.g_countdownLeaveTeamDict:
        PyGameData.g_countdownLeaveTeamDict.pop(playerID)
        
    if curTeamID == 0:
        #ÕâÀï²»ÄܺͼÒ×åÒ»Ñù²¹¾È
        #ÒòΪ×é¶Ó×î´ó6ÈË, Èç¹û²¹¾ÈÁË, ¿ÉÄܳöÏÖ7È˵ÄÇé¿ö
        #ÓÚ2009.8.28³¢ÊÔÔٴβ¹¾È
        #ÀíÂÛÉϲ»»á³öÏÖ7È˶ÓÎé
        curTeamMember = GameWorld.GetTeamManager().FindTeamMemberIndex(playerID)
        if curTeamMember == None:
            return
        curTeamID = curTeamMember.GetTeamID()
        
        curTeam = GameWorld.GetTeamManager().FindTeam(curTeamID)
        if curTeam == None:
            return
        
        #ÔÊÐí´æÔÚµ¥È˶ÓÎ飬ÔÝÆÁ±Î¸ÃÂß¼
#        if curTeam.GetTeamPlayerCount() <= 1:
#            #²¹¾ÈÍê±Ï, ¶ÓÎéÖÐÖ»ÓÐÒ»¸öÈË, ɾ³ýÕâ¸ö¶ÓÎé
#            GameWorld.Log('Íæ¼Ò(%s)ÈÔÈ»ÓжÓÎé(%s), ²¹¾ÈÍê±Ï, ¶ÓÎéÖÐÖ»ÓÐÒ»¸öÈË, ɾ³ýÕâ¸ö¶ÓÎé' % (playerID, curTeamID))
#            DeleteTeam(curTeam, tick)
#            return
        GameWorld.Log('Íæ¼Ò(%s)ÈÔÈ»ÓжÓÎé(%s), ²¹¾È' % (playerID, curTeamID))
        curPlayer.SetTeamID(curTeamID)
        
    curTeam = GameWorld.GetTeamManager().FindTeam(curTeamID)
    if curTeam == None or curTeam.GetMemberByID(playerID) == None:
        #Íæ¼ÒÒѾÀ뿪¶ÓÎéÁË
        curPlayer.SetTeam(None)
        curPlayer.Sync_LeaveTeam(1)
        #֪ͨMapServer, Íæ¼ÒÒѾ¶ÓÎéÁË, Ë¢ÐÂÍæ¼ÒµÄTeamID
        #curPlayer.MapServer_Sync_Team(0)
        SyncMapServerPlayerLeaveTeam(curPlayer, curTeamID)
        gameMap = GameWorld.GetMap(curPlayer.GetMapID())
        if gameMap and gameMap.GetMapFBType() == ChConfig.fbtTeam:
            curPlayer.MapServer_LeaveFB()
        return
    
    curTeamMember = curTeam.GetMemberByID(playerID)
    #Íæ¼ÒµÇ¼, ´ÓTeamMemberÐÅÏ¢ÖжÁÈëÍæ¼ÒµÄ×é¶ÓÐÅÏ¢
    curPlayer.SetTeam(curTeam)
    curTeamMember.SetPlayer(curPlayer)
    
    if curTeamMember.GetTeamLV() == IPY_GameServer.tmlLeader:
        #Êý¾ÝÅж¨, Íæ¼ÒµÇÈëµÄʱºò, Èç¹ûÊǶӳ¤, ÄÇôȡÏûËûµÄ¶Ó³¤È¨ÏÞ
        #<¶Ó³¤ÏÂÏß, ȨÏÞ»á×ªÒÆ>
        #<ÉÏÏßµÄʱºò, ÔÚÏÂÃæ»á¸ø¶Ó³¤µÄ>
        curTeamMember.SetTeamLV(IPY_GameServer.tmlMember)
        
    #»ñµÃÊ£ÓàÈËÊý
    onLineCount = CheckTeamOnLineCount(curTeam)
    if onLineCount <= 1 or not GetTeamLeader(curTeam):
        curTeamMember = curTeam.GetMemberByID(playerID)
        curTeamMember.SetTeamLV(IPY_GameServer.tmlLeader)
        AddTeamIDToSceneList(curTeamID, curPlayer.GetMapID(), tick)
        AddTeamIDToTagMapTeamDict(curTeamID, curTeam.GetTagMapID())
        
    #֪ͨMapServerd¶ÓÎé±ä¸ü
#    curPlayer.MapServer_Sync_Team(curTeamMember.GetTeamLV())
    #֪ͨ¶ÓÎé³ÉÔ±Íæ¼ÒÐÅÏ¢
    #curTeam.Sync_TeamState()
    Sync_TeamMemberInfo(curTeam)
    SyncMapServerTeamInfo(curTeam, "Login", {"playerID":playerID})
    
    if not PlayerControl.GetIsTJG(curPlayer):
        #֪ͨ×Ô¼º¶ÓÎéÍæ¼ÒÉÏÏß
        curPlayer.Sync_TeamMemberLogin() # 09 12 ¶ÓÎé³ÉÔ±ÉÏÏß/ÏÂÏß#tagTeamMemberLoginInfo
    
    #°Ñ×Ô¼ºµÄ״̬ͬ²½¸ø¶ÓÎéËùÓÐÈË
    #curPlayer.Sync_TeamMemberState() # 09 14 ¿çµØÍ¼³ÉÔ±ÐÅÏ¢#tagTeamMemberState
    #°ÑÆäËûÍæ¼ÒµÄÐÅϢ֪ͨ¸øÕâ¸öÍæ¼Ò
    #curTeam.Sync_OtherTeamMemberInfoToCurPlayer(curPlayer) # 09 14 ¿çµØÍ¼³ÉÔ±ÐÅÏ¢#tagTeamMemberState
    
    #Èç¹û¶ÓÎéÕýÔÚÆ¥ÅäÖУ¬Ôò֪ͨ״̬
    if IsTeamMatchingPlayer(curTeamID):
        Sync_TeamMatchState(curPlayer, True)
    return True
#---------------------------------------------------------------------
def OnPlayerReadMapOK(curPlayer, tick):
    ##Íæ¼ÒµÇ½µØÍ¼³É¹¦, Ë¢ÐÂ×é¶Ó״̬
    # @remarks Íæ¼ÒµÇ¼, ³õʼ»¯Íæ¼ÒµÄ¶ÓÎé, ÔÚµØÍ¼µØÍ¼³É¹¦µÄʱºò
    
    GameWorld.DebugLog("Team.OnPlayerReadMapOK", curPlayer.GetPlayerID())
    
    # µÇ¼Âß¼ÒÑ´¦Àí£¬ÕâÀï²»ÖØ¸´´¦Àí
    #===============================================================================================
    # if curPlayer.GetTeamID() == 0:
    #    return
    #    
    # curTeam = GameWorld.GetTeamManager().FindTeam(curPlayer.GetTeamID())
    # if curTeam == None:
    #    #֪ͨMapServer, Íæ¼ÒÒѾ¶ÓÎéÁË, Ë¢ÐÂÍæ¼ÒµÄTeamID
    #    curPlayer.MapServer_Sync_Team(0)
    #    return
    # 
    # SyncMapServerTeamInfo(curTeam)
    # #curTeamMember = curTeam.GetMemberByID(curPlayer.GetPlayerID())
    # ##֪ͨMapServerd¶ÓÎé±ä¸ü
    # #curPlayer.MapServer_Sync_Team(curTeamMember.GetTeamLV())
    #===============================================================================================
    return True
#---------------------------------------------------------------------
##×é¶ÓÍæ¼ÒÇл»µØÍ¼
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ×é¶ÓÍæ¼ÒÇл»µØÍ¼
def OnPlayerChangeMap(curPlayer, tick):
    #---ûÓжÓÎéҲҪ֪ͨ---
    
    mapID = curPlayer.GetMapID()
    GameWorld.DebugLog("Team.OnPlayerChangeMap,mapID=%s" % mapID, curPlayer.GetPlayerID())
    
    playerID = curPlayer.GetPlayerID()
    DelPlayerIDFromSceneList(playerID)
    AddPlayerIDToSceneList(playerID, mapID)
    
    #֪ͨµØÍ¼·þÎñÆ÷¸üÐÂ
    #curPlayer.MapServer_Sync_Team(__GetPlayerTeamLV(curPlayer))
    
    gameMap = GameWorld.GetMap(mapID)
    
    #---ÓжÓÎé²Å֪ͨ---
    curTeam = curPlayer.GetTeam()
    
    if curTeam != None:
        SyncMapServerTeamInfo(curTeam, "ChangeMap", {"playerID":playerID, "mapID":mapID})
        #֪ͨ¿Í»§¶Ë¸üÐÂ
        curPlayer.Sync_TeamMemberChangeMap() # 09 13 ¶ÓÎé³ÉÔ±Çл»µØÍ¼#tagTeamMemberChangeMap
        
        #curTeam.Sync_TeamState()
        #Sync_TeamMemberInfo(curTeam) ÔÝʱ¹Øµô, Ç°ÃæÒѾ֪ͨÇеØÍ¼ÁË£¬ÕâÀï¿É²»Í¨Öª
        
        curPlayerTeamLv = __GetPlayerTeamLV(curPlayer)
        if curPlayerTeamLv == IPY_GameServer.tmlLeader:
            #±ä¸ü³¡¾°¶ÓÎéÁбí
            teamID = curTeam.GetTeamID()
            DelTeamIDFromSceneList(teamID, tick)
            AddTeamIDToSceneList(teamID, curPlayer.GetMapID(), tick)
            
            # ¶Ó³¤½øÈë×é¶Ó¸±±¾£¬ÔòֹͣƥÅ䣬¶ÓÔ±¿ÉÄÜÖ÷¶¯½øÈë×é¶Ó¸±±¾
            if gameMap.GetMapFBType() == ChConfig.fbtTeam:
                DelTeamIDFromMatchingList(curTeam)
                
        curMapData = GameWorld.GetMap(mapID)
        if curMapData and curMapData.GetTeamLimit() == 2:
            DoPlayerLeaveTeam(curPlayer, curTeam, tick)
    else:
        # Íæ¼Ò½øÈë×é¶Ó¸±±¾£¬ÔòֹͣƥÅä
        if gameMap.GetMapFBType() == ChConfig.fbtTeam:
            DelPlayerIDFromMatchingList(curPlayer)
        SyncMapServerPlayerNoTeam(curPlayer) # ûÓжÓÎéµÄʱºòÇÐͼҲ֪ͨµØÍ¼
        
    return
def PlayerTeamMemberRefresh(curPlayer, refreshType, value, tick):
    playerID = curPlayer.GetPlayerID()
    
    # Íæ¼ÒÆ¥Åä¶ÓÎéÖÐÉý¼¶
    if refreshType == IPY_GameServer.CDBPlayerRefresh_LV:
        playerMatchInfo = IsPlayerMatchingTeam(playerID)
        if playerMatchInfo:
            tagMapID, tagMapEx = playerMatchInfo
            GameWorld.DebugLog("Íæ¼ÒÆ¥Åä¶ÓÎéÖÐÉý¼¶, refreshType=%s, value=%s, tagMapID=%s, tagMapEx=%s" 
                               % (refreshType, value, tagMapID, tagMapEx), playerID)
            DoTeamMatchingProcess(tagMapID, tagMapEx, tick)
            
    curTeam = curPlayer.GetTeam()
    if curTeam == None:
        return
        
    teamMember = curTeam.GetMemberByID(playerID)
    if not teamMember:
        return
    GameWorld.DebugLog("¶ÓÎé³ÉÔ±ÊôÐÔË¢ÐÂ, refreshType=%s,value=%s" % (refreshType, value), playerID)
    
    # Ö»¸üеȼ¶¡¢Ö°Òµ¡¢Ö°Òµ½×¡¢¾³½ç; µØÍ¼ÐÅÏ¢ÓɵØÍ¼±ä¸ü֪ͨ    
    if refreshType == IPY_GameServer.CDBPlayerRefresh_LV:
        teamMember.SetPlayerLV(value)
    elif refreshType == IPY_GameServer.CDBPlayerRefresh_Job:
        teamMember.SetPlayerJob(value)
    elif refreshType == IPY_GameServer.CDBPlayerRefresh_ExAttr1:
        teamMember.SetPlayerJobLevel(value)
    elif refreshType == IPY_GameServer.CDBPlayerRefresh_OfficialRank:
        teamMember.SetPlayerRealmLV(value)
    elif refreshType in [IPY_GameServer.CDBPlayerRefresh_VIPLv, IPY_GameServer.CDBPlayerRefresh_ExAttr9]:
        SyncMapServerTeamInfo(curTeam, "Refresh", {"refreshType":refreshType, "value":value})
    else:
        return
    
    #curPlayer.Sync_TeamMemberState() # //09 14 ¿çµØÍ¼³ÉÔ±ÐÅÏ¢#tagTeamMemberState
    #ֻ֪ͨҪ֪ͨµÄ
    #֪ͨ¿Í»§¶Ë
    tmRefresh = ChPyNetSendPack.tagGCTeamMemberRefreshProperty()
    tmRefresh.PlayerID = playerID
    tmRefresh.RefreshType = refreshType
    tmRefresh.Value = value
    SendTeamFakePack(curTeam, tmRefresh)
    return
#// B9 06 ²éѯ¶ÔÓ¦×é¶ÓÄ¿±êµÄ¶ÓÎé #tagCGQueryTagMapTeam
#
#struct    tagCGQueryTagMapTeam
#{
#    tagHead        Head;
#    DWORD        TagMapID;    // Ä¿±êµØÍ¼
#    WORD        TagMapEx;    // Ä¿±êµØÍ¼À©Õ¹
#    BYTE        IsTagEx;        // ÊÇ·ñ²éѯ¶ÔӦĿ±êÀ©Õ¹µÄ; 0·ñ1ÊÇ
#    BYTE        MatchState;    // 0-È«²¿£»1-Æ¥ÅäÖеģ»
#};
def OnQueryTagMapTeam(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    tagMapID = clientData.TagMapID
    tagMapEx = clientData.TagMapEx
    isTagEx = clientData.IsTagEx
    matchState = clientData.MatchState
    
    teamPack = ChPyNetSendPack.tagGCTagMapTeamList()
    teamPack.TagMapID = tagMapID
    teamPack.TagMapEx = tagMapEx
    teamPack.IsTagEx = isTagEx
    teamPack.MatchState = matchState
    teamPack.TeamList = []
    
    teamMgr = GameWorld.GetTeamManager()
    teamIDList = PyGameData.g_tagMapTeamDict.get(tagMapID, [])
    for teamID in teamIDList:
        team = teamMgr.FindTeam(teamID)
        if not team:
            continue
        
        # ÐèҪƥÅäµØÍ¼À©Õ¹µÄ
        if isTagEx and team.GetTagMapEx() != tagMapEx:
            continue
        
        # ֻҪƥÅäÖеĶÓÎé
        if matchState and not IsTeamMatchingPlayer(teamID):
            continue
        
        leader = GetTeamLeader(team)
        if not leader:
            continue
        
        tagMapTeam = ChPyNetSendPack.tagGCTagMapTeam()
        tagMapTeam.PlayerID = leader.GetPlayerID()
        tagMapTeam.PlayerName = leader.GetName()
        tagMapTeam.NameLen = len(tagMapTeam.PlayerName)
        tagMapTeam.LV = leader.GetLV()
        tagMapTeam.Job = leader.GetJob()
        tagMapTeam.JobLevel = PlayerControl.GetJobRank(leader)
        tagMapTeam.RealmLV = leader.GetOfficialRank()
        tagMapTeam.MemberCount = team.GetTeamPlayerCount()
        tagMapTeam.ReqMinLV = team.GetReqMinLV()
        tagMapTeam.ReqMaxLV = team.GetReqMaxLV()
        teamPack.TeamList.append(tagMapTeam)
        
    teamPack.TeamCount = len(teamPack.TeamList)
    NetPackCommon.SendFakePack(curPlayer, teamPack)
    return
#// B9 07 ×Ô¶¯Æ¥Åä¶ÓÎé»òÍæ¼Ò #tagCGAutoMatchTeam
#
#struct    tagCGAutoMatchTeam
#{
#    tagHead        Head;
#    DWORD        TagMapID;    // Ä¿±êµØÍ¼; ·¢0´ú±íÆ¥Å䵱ǰ³¡¾°µÄ
#    WORD        TagMapEx;    // Ä¿±êµØÍ¼À©Õ¹
#};
def OnAutoMatchTeam(index, clientData, tick):
    '''
    ÓжÓÎéµÄÇé¿ö£º Ö»Óжӳ¤ÔÚÎҵĶÓÎé½çÃæ²ÅÄÜÆô¶¯×Ô¶¯Æ¥Å䣬ÆäËû½çÃæ¼°¶ÓÔ±¶¼¿´²»µ½×Ô¶¯Æ¥Åä°´Å¥£¬ËùÒÔÒ»¶¨ÊÇ´´½¨µÄ¶ÓÎéÄ¿±ê
    ÎÞ¶ÓÎéµÄÇé¿ö£º Íæ¼ÒÑ¡ÄÄÀï¾ÍÊÇҪƥÅäÄÄÀïµÄ£¬Ö»ÓÐÎÞ¶ÓÎéµÄ
    '''
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    
    packTagMapID = clientData.TagMapID
    # ·¢2ʱ´ú±íÖúսƥÅä
    if packTagMapID == 2:
        __DoMatchHelpFightTeam(curPlayer, tick)
        return
    
    tagMapEx = clientData.TagMapEx
    tagMapID = packTagMapID
    curMapID = curPlayer.GetMapID()
    
    curTeam = curPlayer.GetTeam()
    if curTeam:
        # Ñé֤ȨÏÞ£¬Ö»Óжӳ¤²ÅÄÜ·¢ÆðÆ¥Åä
        curPlayerTeamLv = __GetPlayerTeamLV(curPlayer)
        if curPlayerTeamLv != IPY_GameServer.tmlLeader:
            GameWorld.Log("Íæ¼Ò²»ÊǶӳ¤£¬ÎÞ·¨·¢ÆðÆ¥Åä! curPlayerTeamLv=%s" % (curPlayerTeamLv), curPlayer.GetPlayerID())
            return
        # ÓжÓÎéµÄĬÈÏÖ»ÄÜÆ¥Å䵱ǰ¶ÓÎéÄ¿±êµÄ
        tagMapID = curTeam.GetTagMapID()
        tagMapEx = curTeam.GetTagMapEx()
        if not tagMapID:
            GameWorld.Log("ÎÞÄ¿±ê¶ÓÎé²»ÔÊÐíÆ¥Å䣡", curPlayer.GetPlayerID())
            return
        
    if tagMapID in [0, 1] or PlayerControl.GetIsTJG(curPlayer):
        tagMapID = curMapID
        
    fbLineIpyData = PlayerFB.GetFBLineIpyData(tagMapID, tagMapEx)
    sceneMapID = tagMapID if not fbLineIpyData else fbLineIpyData.GetMapID()
    GameWorld.DebugLog("ÇëÇóÆ¥Åä¶ÓÎé: curMapID=%s,packTagMapID=%s,tagMapID=%s,tagMapEx=%s,sceneMapID=%s" 
                       % (curMapID, packTagMapID, tagMapID, tagMapEx, sceneMapID), curPlayer.GetPlayerID())
    gameMap = GameWorld.GetMap(sceneMapID)
    if not gameMap:
        GameWorld.ErrLog("Ä¿±êµØÍ¼²»´æÔÚ£¬ÎÞ·¨Æ¥Åä!tagMapID=%s,sceneMapID=%s" % (tagMapID, sceneMapID), curPlayer.GetPlayerID())
        return
    
    # ·Ç×é¶Ó¸±±¾µÄÖ´ÐÐÒ»´ÎÐÔÆ¥ÅäÂß¼, ĬÈÏÆ¥Å䵱ǰ³¡¾°
    if gameMap.GetMapFBType() != ChConfig.fbtTeam:
        if curTeam:
            __DoMatchScenePlayer(curPlayer, curTeam, curMapID, tick)
        else:
            __DoMatchSceneTeam(curPlayer, curMapID, tick)
        return
    
    OnEnterFBTeamAsk(curPlayer, TeamFBAskType_Match, tagMapID, tagMapEx, tick)
    return
def __DoAddToMatchingList(curPlayer, tagMapID, tagMapEx, tick):
    curTeam = curPlayer.GetTeam()
    #¸±±¾Ôò¼ÓÈë×Ô¶¯Æ¥Åä¶ÓÁÐ
    if curTeam:
        DelTeamIDFromMatchingList(curTeam)
        AddTeamIDToMatchingList(curTeam, tagMapID, tagMapEx)
    else:
        DelPlayerIDFromMatchingList(curPlayer)
        AddPlayerIDToMatchingList(curPlayer, tagMapID, tagMapEx)
        
    #ÓÐжÓÎé/Íæ¼Ò¼ÓÈëÆ¥Åäʱ´¦ÀíÒ»´Î
    DoTeamMatchingProcess(tagMapID, tagMapEx, tick)
    return
def __DoMatchSceneTeam(curPlayer, mapID, tick):
    '''Ò»´ÎÐÔÆ¥Åä¶ÓÎé, ͬһµØÍ¼³¡¾°ÖÐ, ¶ÓÎéÄ¿±ê²»ÐèÒªÒ»Ñù
        Ìõ¼þ£º ÏÞÖÆµÈ¼¶·ûºÏ£¬¶ÓÎéδÂú£¬×Ô¶¯½ÓÊÜÈë¶ÓÉêÇëµÄ¶ÓÎé »ò ÍÑ»ú¹Ò»ú¶ÓÎé
        ÍÑ»úÍæ¼ÒÓÅÏÈ×éÍÑ»ú¶ÓÎé, ÔÚÏßÍæ¼ÒÓÅÏÈ×éÔÚÏß¶ÓÎé
    '''
    
    playerID = curPlayer.GetPlayerID()
    curLV = curPlayer.GetLV()
    matchTeamOLList = [] # ÔÚÏß¶ÓÎ飬¶Ó³¤ÎªÔÚÏß״̬
    matchTeamTJList = [] # ÍÑ»ú¶ÓÎ飬¶Ó³¤ÎªÍÑ»ú״̬
    sceneTeamDict = GetSceneTeamIDDict()
    sceneTeamIDList = sceneTeamDict.get(mapID, [])
    teamMgr = GameWorld.GetTeamManager()
    isTJG = PlayerControl.GetIsTJG(curPlayer)
    GameWorld.DebugLog("Íæ¼ÒÆ¥ÅäÄ¿±êµØÍ¼·Ç¸±±¾, Ò»´ÎÐÔÆ¥Å䳡¾°¶ÓÎé: isTJG=%s,curLV=%s,mapID=%s,sceneTeamIDList=%s" 
                       % (isTJG, curLV, mapID, sceneTeamIDList), playerID)
    tjgKickTeamIDList = [] if not isTJG else PyGameData.g_tjgKickPlayerTeamDict.get(playerID, [])
    
    for teamID in sceneTeamIDList:
        
        # Ìß¹ýÍÑ»úÍæ¼ÒµÄ¶ÓÎé²»ÔÙ×é¸ÃÍÑ»úÍæ¼Ò
        if teamID in tjgKickTeamIDList:
            continue
        
        team = teamMgr.FindTeam(teamID)
        if not team:
            continue
        
        if team.IsTeamFull():
            continue
        
        if not (team.GetReqMinLV() <= curLV <= team.GetReqMaxLV()):
            continue
        
        #Æ¥ÅäÖеĶÓÎé²»Äܱ»Ò»´ÎÐÔÆ¥Åä½øÀ´
        if IsTeamMatchingPlayer(teamID):
            continue
        
        leader = GetTeamLeader(team)
        if not leader:
            continue
        
        # ÍÑ»ú¶ÓÎé »ò Èë¶Ó²»ÐèÒªÉóºËµÄ
        isLeaderTJG = PlayerControl.GetIsTJG(leader)
        if isLeaderTJG or not IsTeamJoinReqNeedCheck(leader):
            leaderLV = leader.GetLV()
            teamInfo = [abs(curLV - leaderLV), -leaderLV, leader.GetPlayerID(), team, leader]
            if isLeaderTJG:
                matchTeamTJList.append(teamInfo)
            else:
                matchTeamOLList.append(teamInfo)
    
    if matchTeamOLList:
        matchTeamOLList.sort() # µÈ¼¶²î¾ø¶ÔÖµÉýÐòÅÅ£¬ ¾ø¶ÔÖµÏàͬµÄµÈ¼¶¸ßµÄÅÅÇ°Ãæ
    if matchTeamTJList:
        matchTeamTJList.sort() # µÈ¼¶²î¾ø¶ÔÖµÉýÐòÅÅ£¬ ¾ø¶ÔÖµÏàͬµÄµÈ¼¶¸ßµÄÅÅÇ°Ãæ
        
    if isTJG:
        matchTeamList = matchTeamTJList + matchTeamOLList
    else:
        matchTeamList = matchTeamOLList + matchTeamTJList
        
    for teamInfo in matchTeamList:
        tagTeam = teamInfo[3]
        leader = teamInfo[4]
        if not tagTeam or not leader:
            continue
        
        # ³É¹¦¼ÓÈë¼´½áÊø
        if DoPlayerJoinTeam(curPlayer, leader, tagTeam, tick):
            PlayerControl.NotifyCode(curPlayer, "TeamMatchingSucceed")
            return
        
    PlayerControl.NotifyCode(curPlayer, "NoMatchingTeam")
    return
def __DoMatchScenePlayer(curPlayer, curTeam, mapID, tick):
    '''Ò»´ÎÐÔÆ¥ÅäÍæ¼Ò, ͬһµØÍ¼³¡¾°ÖÐ
        Ìõ¼þ£º µÈ¼¶·ûºÏ¶ÓÎéÐèÇó£¬ÎÞ¶ÓÎ飬×Ô¶¯½ÓÊÜÑûÇëÈë¶Ó »ò ÍÑ»ú¹Ò»úÍæ¼Ò
        ÍÑ»ú¶ÓÎéÓÅÏÈ×éÍÑ»úÍæ¼Ò, ÔÚÏß¶ÓÎéÓÅÏÈ×éÔÚÏßÍæ¼Ò
    '''
    
    curPlayerID = curPlayer.GetPlayerID()
    curPlayerLV = curPlayer.GetLV()
    teamID = curTeam.GetTeamID()
    reqMinLV = curTeam.GetReqMinLV()
    reqMaxLV = curTeam.GetReqMaxLV()
    isLeaderTJG = PlayerControl.GetIsTJG(curPlayer)
    GameWorld.DebugLog("¶ÓÎéÄ¿±êµØÍ¼·Ç¸±±¾, Ò»´ÎÐÔÆ¥Å䳡¾°Íæ¼Ò: teamID=%s,isLeaderTJG=%s,mapID=%s,reqMinLV=%s,reqMaxLV=%s" 
                       % (teamID, isLeaderTJG, mapID, reqMinLV, reqMaxLV), curPlayerID)
    
    matchPlayerOLList = [] # ÔÚÏßÍæ¼Ò
    matchPlayerTJList = [] # ÍÑ»úÍæ¼Ò
    scenePlayerIDDict = GetScenePlayerIDDict()
    scenePlayerIDList = scenePlayerIDDict.get(mapID, [])
    
    playerMgr = GameWorld.GetPlayerManager()
    for playerID in scenePlayerIDList:
        player = playerMgr.FindPlayerByID(playerID)
        if not player:
            continue
        
        if player.GetTeamID():
            continue
        
        # Æ¥ÅäÖеÄÍæ¼Ò²»Äܱ»Ò»´ÎÐÔÆ¥Åä½øÀ´
        if IsPlayerMatchingTeam(playerID):
            continue
        
        playerLV = player.GetLV()
        if not (reqMinLV <= playerLV <= reqMaxLV):
            continue
        
        # ÍÑ»ú¶ÓÎé »ò Èë¶Ó²»ÐèÒªÉóºËµÄ
        isTJG = PlayerControl.GetIsTJG(player)
        if isTJG:
            tjgKickTeamIDList = PyGameData.g_tjgKickPlayerTeamDict.get(playerID, [])
            if teamID in tjgKickTeamIDList:
                continue
            
        if isTJG or not IsTeamInvateNeedCheck(player):
            playerInfo = [abs(curPlayerLV - playerLV), -playerLV, player.GetPlayerID(), player]
            if isTJG:
                matchPlayerTJList.append(playerInfo)
            else:
                matchPlayerOLList.append(playerInfo)
        
    if matchPlayerOLList:
        matchPlayerOLList.sort() # µÈ¼¶²î¾ø¶ÔÖµÉýÐòÅÅ£¬ ¾ø¶ÔÖµÏàͬµÄµÈ¼¶¸ßµÄÅÅÇ°Ãæ
    if matchPlayerTJList:
        matchPlayerTJList.sort() # µÈ¼¶²î¾ø¶ÔÖµÉýÐòÅÅ£¬ ¾ø¶ÔÖµÏàͬµÄµÈ¼¶¸ßµÄÅÅÇ°Ãæ
        
    if isLeaderTJG:
        matchPlayerList = matchPlayerTJList + matchPlayerOLList
    else:
        matchPlayerList = matchPlayerOLList + matchPlayerTJList
        
    joinPlayerCnt = 0
    for playerInfo in matchPlayerList:
        joinPlayer = playerInfo[3]
        if not joinPlayer:
            continue
        
        if DoPlayerJoinTeam(joinPlayer, curPlayer, curTeam, tick):
            joinPlayerCnt += 1
            # ¼Óµ½¶ÓÎéÂúΪֹ
            if curTeam.IsTeamFull():
                GameWorld.DebugLog("    ¶ÓÎéÒÑÂú£¡Í˳öÆ¥Å䣡", curPlayerID)
                break
            
    GameWorld.DebugLog("    ³É¹¦Ôö¼Ó¶ÓÔ±Êý: joinPlayerCnt=%s" % (joinPlayerCnt), curPlayerID)
    if not joinPlayerCnt:
        PlayerControl.NotifyCode(curPlayer, "NoMatchingPlayer")
    else:
        PlayerControl.NotifyCode(curPlayer, "TeamMatchingSucceed")
    return
def __DoMatchHelpFightTeam(curPlayer, tick):
    ''' Ò»´ÎÐÔÆ¥ÅäÐèÒªÖúÕ½µÄ¶ÓÎ飬Âú×ã¶ÓÎéÌõ¼þ×Ô¶¯¼ÓÈëÆ¥Åä¶ÓÎé
            °´ÒÔÏÂÓÅÏȼ¶¼ÓÈ룺
        ´ó¾³½ç¶É½Ù    > ËùÓÐ×ÚÃÅÊÔÁ¶  > ËùÓÐæ´»ÊÒż£  > »ìÂÒÑýÓò
        ×Ô¼ºÓжÓÎéʱ·¢ËÍÖúÕ½º°»°²»Ö´ÐдËÂß¼  
    '''
    curTeam = curPlayer.GetTeam()
    if curTeam:
        return
    
    matchingTeamDict = PyGameData.g_matchingTeamDict
    GameWorld.DebugLog("__DoMatchHelpFightTeam matchingTeamDict=%s" % (matchingTeamDict), curPlayer.GetPlayerID())
    if not matchingTeamDict:
        return
    
    playerLV = curPlayer.GetLV()
    matchMapIDList = [ChConfig.Def_FBMapID_DuJie, ChConfig.Def_FBMapID_MunekadoTrial, ChConfig.Def_FBMapID_QueenRelics, ChConfig.Def_FBMapID_ChaosDemon]
    
    teamMgr = GameWorld.GetTeamManager()
    for matchMapID in matchMapIDList:
        matchTeamInfoList = []
        for key, teamIDList in matchingTeamDict.items():
            tagMapID, tagMapEx = key
            if tagMapID != matchMapID:
                continue
            
            for teamID in teamIDList:
                team = teamMgr.FindTeam(teamID)
                if not team:
                    continue
                
                reqMinLV = team.GetReqMinLV()
                reqMaxLV = team.GetReqMaxLV()
                
                if not (reqMinLV <= playerLV <= reqMaxLV):
                    continue
                
                onLineCount = CheckTeamOnLineCount(team)
                # ÓÅÏȼ¶: ÈËÊý¶àµÄ > Ïß·¼òµ¥µÄ > ¶ÓÎéÈËÊý¶àµÄ ...
                matchTeamInfoList.append([onLineCount, 999999 - tagMapEx, team.GetTeamPlayerCount(), teamID, team])
                
        if not matchTeamInfoList:
            GameWorld.DebugLog("    ûÓÐÂú×ãÖúÕ½µÈ¼¶Ìõ¼þÆ¥ÅäÖеĶÓÎé: matchMapID=%s" % (matchMapID))
            continue
        
        matchTeamInfoList.sort(reverse=True) # µ¹ÐòÅÅ
        GameWorld.DebugLog("    Æ¥Åä¶ÓÎé˳Ðò: matchMapID=%s,%s" % (matchMapID, matchTeamInfoList))
        
        joinTeamID = 0
        for teamInfo in matchTeamInfoList:
            team = teamInfo[-1]
            if not team:
                continue
            
            leader = GetTeamLeader(team)
            if not leader:
                continue
            
            if DoPlayerJoinTeam(curPlayer, leader, team, tick, isAutoMatchJoin=False):
                joinTeamID  = team.GetTeamID()
                break
            
        GameWorld.DebugLog("        joinTeamID=%s" % joinTeamID)
        if joinTeamID:
            break
        
    return
#// B9 08 È¡ÏûÆ¥Åä¶ÓÎé»òÍæ¼Ò #tagCGCancelMatchTeam
#
#struct    tagCGCancelMatchTeam
#{
#    tagHead        Head;
#};
def OnCancelMatchTeam(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curTeam = curPlayer.GetTeam()
    if curTeam:
        # Ñé֤ȨÏÞ£¬Ö»Óжӳ¤²ÅÄÜ·¢ÆðÆ¥Åä
        curPlayerTeamLv = __GetPlayerTeamLV(curPlayer)
        if curPlayerTeamLv != IPY_GameServer.tmlLeader:
            GameWorld.Log("Íæ¼Ò²»ÊǶӳ¤£¬ÎÞ·¨È¡ÏûÆ¥Åä! curPlayerTeamLv=%s" % (curPlayerTeamLv), curPlayer.GetPlayerID())
            return
        DelTeamIDFromMatchingList(curTeam)
    else:
        DelPlayerIDFromMatchingList(curPlayer)    
    return
def DoTeamMatchingProcess(tagMapID, tagMapEx, tick):
    '''×é¶Ó×Ô¶¯Æ¥Åä´¦Àí, Ö»Ðè´¦ÀíÒÔÏÂʱ»ú¼´¿É
    1. ¶ÓÎé »ò Íæ¼Ò ¼ÓÈëÆ¥Åä
    2. Æ¥ÅäÍæ¼Ò¶ÓÁÐÖеÄÍæ¼ÒµÈ¼¶±ä¸üʱ
    '''
    
    key = (tagMapID, tagMapEx)
    matchingTeamDict = PyGameData.g_matchingTeamDict
    matchingPlayerDict = PyGameData.g_matchingPlayerDict
    GameWorld.DebugLog("DoTeamMatchingProcess tagMapID=%s, tagMapEx=%s" % (tagMapID, tagMapEx))
    GameWorld.DebugLog("    matchingTeamDict=%s" % (matchingTeamDict))
    GameWorld.DebugLog("    matchingPlayerDict=%s" % (matchingPlayerDict))
    
    # ûÓÐÆ¥Åä¶ÓÎé »ò Æ¥ÅäÍæ¼Ò Ôò²»´¦Àí
    if key not in matchingTeamDict or key not in matchingPlayerDict:
        GameWorld.DebugLog("    ´¦ÀíÄ¿±êµØÍ¼ÆäÖÐÒ»¸öÆ¥Åä¶ÓÁÐûÓÐÊý¾Ý£¬²»´¦Àí£¡")
        return
    
    teamIDList = matchingTeamDict[key]
    playerIDList = matchingPlayerDict[key]
    if not teamIDList or not playerIDList:
        GameWorld.DebugLog("    ´¦ÀíÄ¿±êµØÍ¼ÆäÖÐÒ»¸öÆ¥Åä¶ÓÁÐûÓÐÊý¾Ý£¬²»´¦Àí£¡")
        return
    
    teamIDList = copy.deepcopy(teamIDList)
    playerIDList = copy.deepcopy(playerIDList)
    delPlayerList = []
    
    teamMgr = GameWorld.GetTeamManager()
    playerMgr = GameWorld.GetPlayerManager()
    
    # ÓÅÏȼÓÈëÈËÊý¶àµÄ¶ÓÎ飬ÈôÈËÊýÏàͬ£¬ÓÅÏȼÓÈëÆ¥Åäʱ¼äÔçµÄ¶ÓÎé
    matchTeamCount = len(teamIDList)
    matchTeamInfoList = []
    for i, teamID in enumerate(teamIDList):
        team = teamMgr.FindTeam(teamID)
        if not team:
            continue
        onLineCount = CheckTeamOnLineCount(team)
        matchTeamInfoList.append([onLineCount, matchTeamCount - i, team.GetTeamPlayerCount(), teamID, team])
    matchTeamInfoList.sort(reverse=True) # µ¹ÐòÅÅ
    GameWorld.DebugLog("    Æ¥Åä¶ÓÎé˳Ðò: %s" % matchTeamInfoList)
    
    for teamInfo in matchTeamInfoList:
        team = teamInfo[-1]
        if not team:
            continue
        
        leader = GetTeamLeader(team)
        if not leader:
            continue
        
        reqMinLV = team.GetReqMinLV()
        reqMaxLV = team.GetReqMaxLV()
        
        for playerID in playerIDList:
            if playerID in delPlayerList:
                continue
            player = playerMgr.FindPlayerByID(playerID)
            if not player:
                continue
            
            if not (reqMinLV <= player.GetLV() <= reqMaxLV):
                continue
            
            if not DoPlayerJoinTeam(player, leader, team, tick, isAutoMatchJoin=True):
                continue
            
            delPlayerList.append(playerID)
            
    return
## ===============================================================================================
# ÒÔÏÂΪ½øÈ븱±¾Á÷³Ì´¦Àí
#// B9 09 ¶ÓÔ±½øÈ븱±¾×¼±¸Ñ¡Ôñ #tagCGTeamMemberPrepare
#
#struct    tagCGTeamMemberPrepare
#{
#    tagHead    Head;
#    BYTE        PrepareState;    // 1-×¼±¸£»2-¾Ü¾ø
#};
def OnTeamMemberPrepare(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    prepareState = clientData.PrepareState
    SetTeamMemberPrepareState(curPlayer, prepareState, tick)
    return
def SetTeamMemberPrepareState(curPlayer, state, tick):
    ''' ÉèÖöÓÔ±½øÈ븱±¾×¼±¸×´Ì¬±ä¸ü
    @param state: 1-×¼±¸£»2-¾Ü¾ø£»3-µôÏß; 4-Í˳ö
    @note: µôÏßÔݲ»×öÉÏÏÂÏßÖ§³Ö£¬Ä¿Ç°Ïȼòµ¥´¦Àí£¬Ö±½Ó°Ñ¸Ã³ÉÔ±ÒÆ³ö×¼±¸¶ÓÁÐ
    '''
    curTeam = curPlayer.GetTeam()
    if not curTeam:
        return
    
    teamID = curTeam.GetTeamID()
    playerID = curPlayer.GetPlayerID()
    if state not in TeamMemPrepareStateList:
        #GameWorld.DebugLog("¶ÓÔ±½øÈ븱±¾×¼±¸×´Ì¬±ä¸ü״̬´íÎ󣬲Ù×÷ʧ°Ü£¡state=%s" % (state), playerID)
        return
    if not IsInEnterFBTeamPrepare(teamID):
        #GameWorld.DebugLog("    ¶ÓÎéûÓÐÔÚ½øÈ븱±¾×¼±¸¶ÓÁÐÀÎÞÐè²Ù×÷£¡", playerID)
        return
    askMapID, askMapEx, memStateDict = PyGameData.g_prepareTeamDict[teamID][:3]
    GameWorld.DebugLog("¶ÓÔ±½øÈ븱±¾×¼±¸×´Ì¬±ä¸ü: teamID=%s,state=%s,memStateDict=%s" % (teamID, state, memStateDict), playerID)
    if playerID not in memStateDict:
        #GameWorld.DebugLog("    ³ÉԱûÓÐÔÚ¶ÓÎé×¼±¸ÁбíÀÎÞÐè²Ù×÷£¡memStateDict=%s" % memStateDict, playerID)
        return
    
    # Íæ¼ÒµôÏߣ¬Ö±½ÓÒÆ³ö×¼±¸¶ÓÁÐ
    if state in [TeamMemPrepareState_Offline, TeamMemPrepareState_LeaveTeam]:
        memStateDict.pop(playerID)
    else:
        memStateDict[playerID] = state
        
    teamLeader = GetTeamLeader(curTeam)
    
    isErr = (not memStateDict or not teamLeader)
    # ͬ²½¿Í»§¶Ë
    SyncTeamEnterFBPrepareInfo(curTeam, askMapID, askMapEx, memStateDict, isErr)
    
    # Ö»ÒªÓÐÈ˾ܾø, ±¾´Î½øÈ븱±¾ÇëÇó×÷·Ï
    if state == TeamMemPrepareState_Refuse or isErr:
        PyGameData.g_prepareTeamDict.pop(teamID)
        
        if state == TeamMemPrepareState_Refuse:
            PlayerControl.TeamNotify(teamID, "TeamEnterFailed", [curPlayer.GetName()])
        return
    
    # ʣϵÄÇé¿ö¼ì²éʣϵĶÓÔ±ÊÇ·ñ¶¼ÒѾ׼±¸
    for state in memStateDict.values():
        if state != TeamMemPrepareState_OK:
            return
    
    GameWorld.DebugLog("ËùÓжÓÔ±¶¼×¼±¸ºÃÁË£¬×ö½øÈ븱±¾Ç°×îÖÕ¸´²é£¡", playerID)
    # ¶¼×¼±¸ºÃÁË£¬ÔòÐè×ö×îÖÕ½øÈ븱±¾µ±Ç°×´Ì¬ÔÙ´ÎÈ·ÈÏÊÇ·ñ¶¼Âú×ãÌõ¼þ£¬·¢ÆðÇëÇóµÄ±ØÐëÊǶӳ¤
    OnEnterFBTeamAsk(teamLeader, TeamFBAskType_PrepareOK, askMapID, askMapEx, tick)
    return
def SyncTeamEnterFBPrepareInfo(curTeam, askMapID, askMapEx, memStateDict, isErr=False):
    ## ͬ²½¶ÓÎé½øÈë×é¶Ó¸±±¾¶ÓÔ±×¼±¸×´Ì¬
    teamMemPreparePack = ChPyNetSendPack.tagGCTeamEnterFBPrepare()
    teamMemPreparePack.TagMapID = askMapID
    teamMemPreparePack.TagMapEx = askMapEx
    teamMemPreparePack.IsPrepareErr = isErr
    teamMemPreparePack.MemStateList = []
    for memPlayerID, state in memStateDict.items():
        memState = ChPyNetSendPack.tagGCTeamMemPrepareState()
        memState.PlayerID = memPlayerID
        memState.PrepareState = state
        teamMemPreparePack.MemStateList.append(memState)
    teamMemPreparePack.MemCount = len(teamMemPreparePack.MemStateList)
    SendTeamFakePack(curTeam, teamMemPreparePack)
    return
## ÊÇ·ñÕýÔÚѯÎʿɷñ½øÈë×é¶Ó¸±±¾ÖÐ
def IsInEnterFBTeamPrepare(teamID): return teamID in PyGameData.g_prepareTeamDict
## ÊÇ·ñÕýÔÚ½øÈë×é¶Ó¸±±¾¶ÓÔ±×¼±¸ÖÐ
def IsInEnterFBTeamAsk(teamID): return teamID in PyGameData.g_teamFBEnterAskDict
def OnEnterFBTeamAsk(curPlayer, askType, askMapID, askMapEx, tick):
    '''ѯÎʿɷñ½øÈë×é¶Ó¸±±¾£¬ÓÐÈý¸öʱ¼äµãÐèҪѯÎÊ£¨Æ¥Åäǰ¡¢¶Ó³¤µã»÷½øÈë¡¢¶ÓÔ±¶¼×¼±¸³É¹¦ºó½øÈëǰ×îÖÕÈ·ÈÏ£©
    @param askType: ѯÎÊÀàÐÍ£»0-·¢ÆðÆ¥Åä(¸öÈË¡¢¶Ó³¤)£»1-¶Ó³¤µã»÷½øÈ룻2-×¼±¸Íêºó½øÈëѯÎÊ
    @param tick: ¿É×÷ΪѯÎÊÇëÇóµÄ°æ±¾ºÅ, ×÷ΪÊÇ·ñͬһÇëÇóµÄ»Ø¸´Ó㬷ÀÖ¹¸²¸ÇÇëÇ󻨏´´¦Àí»ìÂÒ
    '''
    playerID = curPlayer.GetPlayerID()
    curTeam = curPlayer.GetTeam()
    askVer = tick
    if curTeam == None:
        teamID = 0
        # ¸öÈË·¢Æð¸±±¾Æ¥ÅäµÄÐèҪѯÎÊÍæ¼ÒËùÔÚµØÍ¼£¬¼ì²éÍæ¼ÒÊÇ·ñ¿É½øÈë
        if askType == TeamFBAskType_Match:
            if not GameWorld.RefurbishPlayerTick(curPlayer, ChConfig.TYPE_Player_Tick_EnterFBTeamAskTick, tick):
                GameWorld.Log("¸öÈËÇëÇó½øÈ븱±¾Æ¥Å䣬ÎÞ·¨Öظ´ÇëÇó! askMapID=%s,askMapEx=%s" % (askMapID, askMapEx), playerID)
                return
            playerMapID = GameWorld.GetQueryPlayerMapID(curPlayer)
            if not playerMapID:
                return
            # ¸öÈ˵ÄÖ»×öѯÎÊCD£¬²»¼Ç¼
            sendCMD = str([teamID, askVer, askType, askMapID, askMapEx])
            GameWorld.GetPlayerManager().MapServer_QueryPlayer(playerID, 0, playerID, playerMapID, "EnterFBTeamAsk", 
                                                               sendCMD, len(sendCMD), curPlayer.GetRouteServerIndex())
            GameWorld.DebugLog("EnterFBTeamAsk ¸öÈË·¢Æð¸±±¾Æ¥ÅäµÄÐèҪѯÎÊÍæ¼ÒËùÔÚµØÍ¼£¬¼ì²éÍæ¼ÒÊÇ·ñ¿É½øÈë", playerID)
            
        #===========================================================================================
        # # ·ÇÆ¥ÅäµÄ¸öÈËÇé¿ö£¬Ò»°ãΪµ¥È˽øÈë×é¶Ó¸±±¾£¬´ËÇé¿öÔÚMapServerÖ±½Ó´¦Àí£¬²»»á×ßµ½ÕâÀï
        # elif askType == TeamFBAskType_Enter:
        #    resultName = str([askMapID, askMapEx])
        #    curPlayer.MapServer_QueryPlayerResult(0, 0, "EnterFBTeamAsk", resultName, len(resultName))
        #===========================================================================================
        return
    
    teamID = curTeam.GetTeamID()
    if IsInEnterFBTeamAsk(teamID):
        # Èç¹ûÒѾÔÚ¶ÓÁÐÀïµÄ£¬ÔòÑéÖ¤ÇëÇóCD£¬µ±¹ýÁ˸ÃCD¿ÉÇ¿ÖÆ¸²¸Ç¸üвéѯ£¬·ÀÖ¹Òì³£Çé¿öijЩ¶ÓԱûÓлØÓ¦µ¼ÖÂÎÞ·¨½øÐÐÏÂÒ»´ÎÇëÇó
        if not GameWorld.RefurbishPlayerTick(curPlayer, ChConfig.TYPE_Player_Tick_EnterFBTeamAskTick, tick):
            GameWorld.Log("¶ÓÎéÇëÇó½øÈ븱±¾ÖУ¬ÎÞ·¨Öظ´ÇëÇó! teamID=%s,askMapID=%s,askMapEx=%s" % (teamID, askMapID, askMapEx), playerID)
            return
        
    askPlayerRetDict = {} # ѯÎʵĶÓÔ±½á¹ûÐÅÏ¢×Öµä³õʼ»¯
    askPlayerMapDict = {} # ѯÎʵĶÓÔ±µØÍ¼ÐÅÏ¢×Öµä
    # µ½¶ÓÔ±ËùÊôµØÍ¼Ñ¯ÎÊÑéÖ¤¶ÓÔ±ÊÇ·ñÂú×ã½øÈ븱±¾Ìõ¼þ
    for i in xrange(curTeam.GetMemberCount()):
        memPlayer = curTeam.GetMemberPlayer(i)
        #curMemberInfo = curTeam.GetMemberInfo(i)
        #¹ýÂ˲»ÔÚÏߵijÉÔ±
        if memPlayer == None or memPlayer.GetPlayerID() == 0:
            continue
        memPlayerID = memPlayer.GetPlayerID()
        memMapID = GameWorld.GetQueryPlayerMapID(memPlayer)
        if not memMapID:
            GameWorld.ErrLog("ÕÒ²»µ½ÔÚÏß¶ÓÔ±ËùÊôµØÍ¼£¬·ÅÆú±¾´Î½øÈë×é¶Ó¸±±¾ÇëÇó£¡memPlayerID=%s" % memPlayerID, playerID)
            return
        
        askPlayerRetDict[memPlayerID] = []
        askPlayerMapDict[memPlayerID] = [memMapID, memPlayer.GetRouteServerIndex()]
        
    UpdateTeamTagMapTime(teamID, askMapID)
    # ûÓÐÐèҪѯÎʵĶÓÔ±£¬Ôò±¾´ÎѯÎÊʧЧ
    if not askPlayerMapDict:
        return
    
    # ¸²¸ÇÌí¼Ó
    PyGameData.g_teamFBEnterAskDict[teamID] = [askVer, askType, askMapID, askMapEx, askPlayerRetDict, tick]
    
    sendCMD = str([teamID, askVer, askType, askMapID, askMapEx])
    for memPlayerID, mapInfo in askPlayerMapDict.items():
        memMapID, routeServerIndex = mapInfo
        GameWorld.GetPlayerManager().MapServer_QueryPlayer(playerID, 0, memPlayerID, memMapID, "EnterFBTeamAsk", 
                                                           sendCMD, len(sendCMD), routeServerIndex)
    GameWorld.DebugLog("Add EnterFBTeamAsk teamID=%s,askVer=%s,askType=%s,askMapID=%s,askMapEx=%s,askPlayerMapDict=%s,askPlayerRetDict=%s" 
                       % (teamID, askVer, askType, askMapID, askMapEx, askPlayerMapDict, askPlayerRetDict), playerID)
    return
def OnEnterFBTeamAskResult(curPlayer, resultList, tick):
    retTeamID, retAskVer, retAskType, retAskMapID, retAskMapEx, retPlayerID, ret, retPlayerName = resultList
    curTeam = curPlayer.GetTeam()
    teamID = curPlayer.GetTeamID()
    playerID = curPlayer.GetPlayerID()
    
    GameWorld.DebugLog("OnEnterFBTeamAskResult retTeamID=%s,retAskVer=%s,retAskType=%s,retAskMapID=%s,retAskMapEx=%s,retPlayerID=%s,ret=%s" 
                       % (retTeamID, retAskVer, retAskType, retAskMapID, retAskMapEx, retPlayerID, ret), playerID)
    # ÕâÀïµÄÅжϰüº¬¶ÓÎéIDΪ0µÄÇé¿ö
    if teamID != retTeamID:
        GameWorld.DebugLog("    ·Çͬ¸ö¶ÓÎéÇëÇ󣬲»´¦Àí£¡teamID=%s,retTeamID=%s" % (teamID, retTeamID), playerID)
        return
    
    notifyRet = ShareDefine.EntFBAskRet_Max
    causePlayerDict = {} # Òý·¢ÎÞ·¨½øÈëµÄ³ÉÔ±ÐÅÏ¢ {playerID:playerName, ...}
    memStateDict = {} # ³ÉÔ±×¼±¸×´Ì¬×Öµä³õʼ»¯ {playerID:ÊÇ·ñÒÑ×¼±¸, ...}
    
    # ¶ÓÎéÇëÇóµÄ
    if retTeamID:
        if retTeamID not in PyGameData.g_teamFBEnterAskDict:
            GameWorld.DebugLog("    ¸Ã¶ÓÎéµÄÇëÇóÐÅÏ¢¼Ç¼ÒѲ»´æÔÚ£¬²»´¦Àí!retTeamID=%s" % retTeamID, playerID)
            return
        askVer, askType, askMapID, askMapEx, askPlayerRetDict = PyGameData.g_teamFBEnterAskDict[retTeamID][:5]
        if askVer != retAskVer or askType != retAskType or askMapID != retAskMapID or askMapEx != retAskMapEx:
            GameWorld.DebugLog("    ·Ç±¾¶ÓÎéÇëÇó°æ±¾£¬²»´¦Àí£¡askVer=%s, askType=%s, askMapID=%s, askMapEx=%s" 
                               % (askVer, askType, askMapID, askMapEx), playerID)
            return
        if retPlayerID not in askPlayerRetDict:
            GameWorld.DebugLog("    ûÓÐÇëÇó¸Ã¶ÓÔ±ID£¬²»´¦Àí!retPlayerID=%s" % retPlayerID, playerID)
            return
        
        # ¸üÐÂÇëÇó¶ÓÔ±½á¹û
        askPlayerRetDict[retPlayerID] = [ret, retPlayerName]
        
        # ¼ì²éѯÎʵĶÓÔ±ÊÇ·ñ¶¼ÒѾ»Ø¸´½á¹û
        for memPlayerID, retInfo in askPlayerRetDict.items():
            if not retInfo:
                # »¹ÓÐδ»Ø¸´µÄ£¬Ôݲ»´¦Àí
                return
            memStateDict[memPlayerID] = int(memPlayerID == playerID) # ¶Ó³¤×Ô¼ºµ±×ö×¼±¸ºÃµÄ
            ret, retPlayerName = retInfo
            if ret == ShareDefine.EntFBAskRet_OK:
                continue
            
            if ret < notifyRet:
                notifyRet = ret
                causePlayerDict = {}
                causePlayerDict[memPlayerID] = retPlayerName
            elif ret == notifyRet:
                causePlayerDict[memPlayerID] = retPlayerName
                
        PyGameData.g_teamFBEnterAskDict.pop(retTeamID) # ÒÆ³ý¸ÃÇëÇó¼Ç¼
        
    # ¸öÈËÇëÇóµÄ
    else:
        if ret != ShareDefine.EntFBAskRet_OK:
            notifyRet = ret
            causePlayerDict[retPlayerID] = retPlayerName
            
    ## ÒÔÏÂÂ߼ΪѯÎʵÄÄ¿±ê¾ù»Ø¸´ºóµÄ´¦Àí£¬´ó²¿·ÖÇé¿öÏÂÄÜѯÎʵÄÍæ¼Ò¶¼»á»Ø¸´£¬Ð¡¸ÅÂÊûÓлظ´µÄÇé¿öµ±×ö´Ë´ÎÂß¼×÷·ÏÎÞÏìÓ¦£¬¶Ó³¤ÖØÐÂÇëÇó¼´¿É
    
    # Óв»ÄܽøÈ븱±¾µÄÔÒò£¬ÐèÒª×öÌáʾ
    if notifyRet != ShareDefine.EntFBAskRet_Max:
        __DoEnterFBTeamAskResultNotify(curPlayer, retAskType, retAskMapID, notifyRet, causePlayerDict, memStateDict.keys())
        
        #¶¼×¼±¸ºÃºó²»ÄܽøÈëÒì³£ÐèÒªÌáʾ¿Í»§¶Ë
        if retAskType == TeamFBAskType_PrepareOK:
            SyncTeamEnterFBPrepareInfo(curTeam, retAskMapID, retAskMapEx, memStateDict, isErr=True)
        return
    
    # ×¢: ¸öÈ˵ÄÖ»ÓÐÆ¥Åä»áѯÎÊ£¬·ÇÆ¥ÅäµÄ¸öÈËÔÚMapServerÒѾÑéÖ¤¹ýÊÇ·ñ¿É½øÈ룬²»»áÔÙ´ÎѯÎÊ£¬¹Ê¸öÈ˵ÄÖ»ÓÐÆ¥ÅäÂß¼²Å»á×ßµ½ÕâÀï
    
    # ȫԱ¼ì²éͨ¹ý£¬¿É½øÈëÏÂÒ»²½Âß¼
    
    # Æ¥ÅäѯÎÊͨ¹ýºóÂß¼
    if retAskType == TeamFBAskType_Match:
        # ¼ÓÈëÆ¥Åä
        __DoAddToMatchingList(curPlayer, retAskMapID, retAskMapEx, tick)
    # ÇëÇó½øÈ븱±¾Ñ¯ÎÊͨ¹ýºóÂß¼
    elif retAskType == TeamFBAskType_Enter:
        if curTeam:
            # µ¥È˶ÓÎéÖ±½Ó½øÈ룬²»ÐèҪ׼±¸
            if len(memStateDict) == 1:
                GameWorld.DebugLog("¶ÓÎéÖ»ÓÐÒ»¸öÈË£¬Ö±½Ó½øÈ븱±¾: memStateDict=%s" % memStateDict, playerID)
                resultName = str([retAskMapID, retAskMapEx])
                curPlayer.MapServer_QueryPlayerResult(0, 0, "EnterFBTeamAsk", resultName, len(resultName))
            # ¶àÈ˶ÓÎ飬¶ÓÎé¼ÓÈë×¼±¸¶ÓÁУ¬Í¨Öª¶ÓÔ±×¼±¸
            else:
                DelTeamIDFromMatchingList(curTeam) # ½øÈë×¼±¸½×¶ÎֹͣƥÅä
                GameWorld.DebugLog("¶ÓÎéÑé֤ͨ¹ý£¬Í¨Öª¶ÓÔ±×¼±¸½øÈ븱±¾: memStateDict=%s" % memStateDict, playerID)
                PyGameData.g_prepareTeamDict[teamID] = [retAskMapID, retAskMapEx, memStateDict, tick]
                SyncTeamEnterFBPrepareInfo(curTeam, retAskMapID, retAskMapEx, memStateDict)
        else:
            # ²»»áÓÐÎÞ¶ÓÎéµÄÇé¿ö×ßµ½ÕâÀï
            pass
        
    # ȫԱ׼±¸Íê±ÏѯÎÊͨ¹ýºóÂß¼
    elif retAskType == TeamFBAskType_PrepareOK:
        # ¶Ó³¤½øÈë
        resultName = str([retAskMapID, retAskMapEx] + GetTeamFBEnterInfo(curPlayer, curTeam, retAskMapID, retAskMapEx))
        curPlayer.MapServer_QueryPlayerResult(0, 0, "EnterFBTeamAsk", resultName, len(resultName))
        GameWorld.Log("¶ÓÔ±×¼±¸Íê±Ï£¬¶Ó³¤½øÈë×é¶Ó¸±±¾: resultName=%s" % resultName, curPlayer.GetPlayerID())
        
    return
def GetTeamFBEnterInfo(leader, curTeam, retAskMapID, retAskMapEx):
    # »ñÈ¡×é¶Ó¸±±¾³É³¤µÈ¼¶, ĬÈÏÆ½¾ùµÈ¼¶, ½ö¼ÆËã±¾´Î×¼±¸½øÈ븱±¾µÄ¶ÓÔ±£¬×¢Òâ²»ÊÇËùÓжÓÔ±
    teamID = curTeam.GetTeamID()
    isInPrepareTeam = IsInEnterFBTeamPrepare(teamID)
    if not isInPrepareTeam:
        return []
    askMapID, askMapEx, memStateDict = PyGameData.g_prepareTeamDict[teamID][:3]
    if retAskMapID != askMapID or retAskMapEx != askMapEx:
        return []
    totalLV = 0
    maxLV = 0
    
    # Ææ¹Ö£¬ÕâÀï±éÀú¶ÓÎéÈ¡²»µ½Íæ¼ÒʾÀý£¬ÏÈÓòéÕÒÍæ¼ÒµÄ
    
    playerMgr = GameWorld.GetPlayerManager()
    for playerID in memStateDict.keys():
        memPlayer = playerMgr.FindPlayerByID(playerID)
        #Ä¿±êÍæ¼ÒÊÇ·ñ´æÔÚ
        if memPlayer == None:
            continue
        
        memLV = memPlayer.GetLV()
        if maxLV < memLV:
            maxLV = memLV 
        totalLV += memLV
        
    if not maxLV:
        return []
    playerCnt = len(memStateDict)
    averageLV = int(totalLV / playerCnt)
    return [averageLV, maxLV, playerCnt]
def __DoEnterFBTeamAskResultNotify(curPlayer, retAskType, askMapID, notifyRet, causePlayerDict, askPlayerIDList):
    # ²»¿É½øÈëÔÒò¶ÔÓ¦ÌáʾÐÅÏ¢×Öµä {ÔÒò:[[×Ô¶¯Æ¥ÅäÒý·¢Íæ¼ÒÌáʾ, ÆäËû¶ÓÔ±Ìáʾ], [ÊÖ¶¯½øÈëÒý·¢Íæ¼ÒÌáʾ, ÆäËû¶ÓÔ±Ìáʾ], µ¥ÈËÌáʾ], ...}
    notifyKeyDict = {
                     ShareDefine.EntFBAskRet_FBClose:[["FBIsNotOpen", "FBIsNotOpen"], 
                                                         ["FBIsNotOpen", "FBIsNotOpen"], "FBIsNotOpen"],
                     ShareDefine.EntFBAskRet_NoEnterCnt:[["TeamMatchingTimeMe", "TeamMatchingTimeAll"], 
                                                         ["TeamEnterTimeMe", "TeamEnterTimeAll"], "GeRen_chenxin_268121"],
                     ShareDefine.EntFBAskRet_EnterCD:[["TeamMatchingCDMe", "TeamMatchingCDAll"], 
                                                      ["TeamEnterCDMe", "TeamEnterCDAll"], "SingleEnterCD"],
                     ShareDefine.EntFBAskRet_LVLimit:[["TeamMatchingLVMe", "TeamMatchingLVAll"], 
                                                      ["TeamEnterLVMe", "TeamEnterLVAll"], "FbLV"],
                     ShareDefine.EntFBAskRet_JobRankLimit:[["TeamMatchingJobMe", "TeamMatchingJobAll"], 
                                                           ["TeamEnterJobMe", "TeamEnterJobAll"], "SingleEnterJob"],
                     ShareDefine.EntFBAskRet_NoTicket:[["TeamMatchingTicketMe", "TeamMatchingTicketAll"], 
                                                       ["TeamEnterTicketMe", "TeamEnterTicketAll"], "GeRen_chenxin_157069"],
                     ShareDefine.EntFBAskRet_Dead:[["TeamMatchingDeadMe", "TeamMatchingDeadAll"], 
                                                   ["TeamEnterDeadMe", "TeamEnterDeadAll"], "SingleEnterDead"],
                     ShareDefine.EntFBAskRet_BossState:[["TeamMatchingBossMe", "TeamMatchingBossAll"], 
                                                        ["TeamEnterBossMe", "TeamEnterBossAll"], "SingleEnterBoss"],
                     ShareDefine.EntFBAskRet_PKState:[["TeamMatchingPKMe", "TeamMatchingPKAll"], 
                                                      ["TeamEnterPKMe", "TeamEnterPKAll"], "SingleEnterPK"],
                     ShareDefine.EntFBAskRet_Preparing:[["TeamMatchingGatherMe", "TeamMatchingGatherAll"], 
                                                        ["TeamEnterGatherMe", "TeamEnterGatherAll"], "SingleEnterGather"],
                     ShareDefine.EntFBAskRet_InFB:[["TeamMatchingDungeonMe", "TeamMatchingDungeonAll"], 
                                                   ["TeamEnterDungeonMe", "TeamEnterDungeonAll"], "SingleEnterDungeon"],
                     ShareDefine.EntFBAskRet_TJG:[["TeamMatchingDefaultMe", "TeamMatchingDefaultAll"], 
                                                   ["TeamEnterDefaultMe", "TeamEnterDefaultAll"], "SingleEnterDefaul"],
                     ShareDefine.EntFBAskRet_Sit:[["TeamMatchingSITMe", "TeamMatchingSITAll"], 
                                                  ["TeamEnterSITMe", "TeamEnterSITAll"], "Carry_lhs_697674"],
                     ShareDefine.EntFBAskRet_Other:[["TeamMatchingDefaultMe", "TeamMatchingDefaultAll"], 
                                                   ["TeamEnterDefaultMe", "TeamEnterDefaultAll"], "SingleEnterDefaul"],
                     }
    
    playerID = curPlayer.GetPlayerID()
    GameWorld.DebugLog("²»¿É½øÈë×é¶Ó¸±±¾ÔÒòÌáÐÑ£ºretAskType=%s,askMapID=%s,notifyRet=%s,causePlayerDict=%s,askPlayerIDList=%s" 
                       % (retAskType, askMapID, notifyRet, causePlayerDict, askPlayerIDList), playerID)
    if notifyRet not in notifyKeyDict:
        GameWorld.DebugLog("×é¶Ó¸±±¾²»¿É½øÈëÔÒòÎÞÌáʾ: retAskType=%s,notifyRet=%s" % (retAskType, notifyRet), playerID)
        return
    matchNotifyList, enterNotifyList, singleNotify = notifyKeyDict[notifyRet]
    
    curTeam = curPlayer.GetTeam()
    if not curTeam:
        notifyMark = matchNotifyList[0] if retAskType == TeamFBAskType_Match else singleNotify
        PlayerControl.NotifyCode(curPlayer, notifyMark, [askMapID]) # ûÓжÓÎéµÄÖ»Ìáʾ×Ô¼º
    else:
        causePlayerName = ShareDefine.Def_Space.join(causePlayerDict.values())
        notifyList = matchNotifyList if retAskType == TeamFBAskType_Match else enterNotifyList
        for index in xrange(curTeam.GetMemberCount()):
            memPlayer = curTeam.GetMemberPlayer(index)
            if not memPlayer:
                continue
            memPlayerID = memPlayer.GetPlayerID()
            if not memPlayerID or memPlayerID not in askPlayerIDList:
                continue
            
            if memPlayerID in causePlayerDict:
                PlayerControl.NotifyCode(memPlayer, notifyList[0], [askMapID])
                if notifyRet in [ShareDefine.EntFBAskRet_NoEnterCnt, ShareDefine.EntFBAskRet_EnterCD, ShareDefine.EntFBAskRet_NoTicket]:
                    failPack = ChPyNetSendPack.tagGCEnterTeamFBFailReason()
                    failPack.MapID = askMapID
                    failPack.AskType = retAskType
                    failPack.Reason = notifyRet
                    NetPackCommon.SendFakePack(memPlayer, failPack)
            else:
                PlayerControl.NotifyCode(memPlayer, notifyList[1], [askMapID, causePlayerName])
    return
#===============================================================================
# #class   IPY_GTeamEnterFB
# #{
# #public:
# #    //ÊÇ·ñ½øÈë
# #    int      GetIsEnter();
# #};
#===============================================================================
##×é¶Ó³ÉÔ±½øÈë¶ÓÎ鸱±¾.
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks MapServer·â°ü´¥·¢, ×é¶Ó³ÉÔ±½øÈë¶ÓÎ鸱±¾
def MapServer_PlayerEnterFB(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curTeam = curPlayer.GetTeam()
    if curTeam == None:
        return
    
    pack = IPY_GameServer.IPY_GTeamEnterFB()
    
    teamMapID = curTeam.GetTeamFBMapID()
    teamMapFBID = curTeam.GetTeamFBMapFBID()
    
    playerID = curPlayer.GetPlayerID()
    playerMapID = curPlayer.GetMapID()
    playerFBID = curPlayer.GetFBID()
    playerDataMapID = PlayerFB.GetRecordMapID(playerMapID)
    
    if pack.GetIsEnter():
        #Èç¹û¶Ó³¤½øÈ븱±¾£¬Ç¿ÖÆÌæ»»×é¶ÓID
        if __GetPlayerTeamLV(curPlayer) == IPY_GameServer.tmlLeader:
            GameWorld.DebugLog("¶Ó³¤½øÈ븱±¾, ¸üÐÂTeamFB! playerMapID=%s,playerFBID=%s,playerDataMapID=%s" 
                               % (playerMapID, playerFBID, playerDataMapID), playerID)
            curTeam.SetTeamFBMapID(playerMapID)
            curTeam.SetTeamFBMapFBID(playerFBID)
            __OnPrepareTeamLeaderEnterFB(curTeam, curPlayer, playerDataMapID, playerMapID, playerFBID)
            
        #Íæ¼Ò½øÈ븱±¾, Èç¹ûµ±Ç°¶ÓÎ鸱±¾IDΪ0 , ÔòÉèÖÃ
        elif teamMapID == 0:
            GameWorld.Log("¶ÓÔ±½øÈ븱±¾, teamMapID²»´æÔÚ£¬Ôò¸üÐÂTeamFB! playerMapID=%s,playerFBID=%s" 
                          % (playerMapID, playerFBID), playerID)
            curTeam.SetTeamFBMapID(playerMapID)
            curTeam.SetTeamFBMapFBID(playerFBID)
            
        #·ñÔò, ºÍ´ËÍæ¼ÒÈç¹û¸±±¾ID²»Í¬, Ìß³ö¸±±¾
        elif teamMapID and teamMapID == playerMapID and teamMapFBID != playerFBID:
            GameWorld.Log('¶ÓÔ±½øÈ븱±¾£¬µ«ÊǽøÈëµÄfbIDÓë¶ÓÎ鲻ͬ£¬Ìß³ö¸ÃÍæ¼Ò£¡teamMapID=%s,teamMapFBID=%s,playerMapID=%s,playerFBID=%s' 
                          % (teamMapID, teamMapFBID, playerMapID, playerFBID), playerID)
            curPlayer.MapServer_LeaveFB()
        else:
            GameWorld.DebugLog("¶ÓÔ±³É¹¦½øÈë¶ÓÎéËùÔÚ¸±±¾£¡teamMapID=%s,teamMapFBID=%s" % (teamMapID, teamMapFBID), playerID)
    else:
        #Íæ¼ÒÀ뿪¸±±¾, Åж¨ÊÇ·ñ»¹ÓÐÍæ¼ÒÔڴ˸±±¾ÖÐ, Èç¹ûÓÐ, ·µ»Ø, ûÓÐ, ¸Ä¸±±¾IDΪ0
        if __CheckTeamFBPlayerExist(curTeam):
            return
        
        curTeam.SetTeamFBMapID(0)
        curTeam.SetTeamFBMapFBID(0)
        #GameWorld.DebugLog("ûÓÐÈËÔÚ¸±±¾ÖÐÁË£¬ÖØÖã¡TeamFBMapID")
    
    return
def __OnPrepareTeamLeaderEnterFB(curTeam, leader, leaderDataMapID, leaderMapID, leaderFBID):
    ## Ö´ÐÐ×¼±¸ÖеĶÓÎé¶Ó³¤³É¹¦½øÈ븱±¾ºóÂß¼
    
    teamID = curTeam.GetTeamID()
    if not IsInEnterFBTeamPrepare(teamID):
        GameWorld.DebugLog("·Ç×¼±¸ÖеĶÓÎé²»´¦Àí£¡")
        return
    askMapID, askMapEx, memStateDict = PyGameData.g_prepareTeamDict[teamID][:3]
    enterInfo = GetTeamFBEnterInfo(leader, curTeam, askMapID, askMapEx)
    
    #Ìß³öËùÓÐÔÚ´ËÀั±¾£¬µ«²»Í¬Ïß·µÄÍæ¼Ò
    for index in xrange(curTeam.GetMemberCount()):
        memPlayer = curTeam.GetMemberPlayer(index)
        if not memPlayer or not memPlayer.GetPlayerID():
            continue
        
        memPlayerID = memPlayer.GetPlayerID()
        memMapID = memPlayer.GetMapID()
        memFBID = memPlayer.GetFBID()
        memDataMapID = PlayerFB.GetRecordMapID(memMapID)
        
        # ·Ç×¼±¸¶ÓÁнøÈëµÄ²»Ìß
        if memDataMapID == leaderDataMapID and (memMapID != leaderMapID or memFBID != leaderFBID):
            GameWorld.Log('Íæ¼ÒÒò×é¶Ó, ÔÚͬ¸±±¾Öв»Í¬Ïß·£¬Ìß³öÍæ¼Ò! memID=%s,memMapID=%s,memFBID=%s' % (memPlayerID, memMapID, memFBID))
            memPlayer.MapServer_LeaveFB()
            
        # ²»ÊÇÔڸø±±¾µÄ ÇÒ ÊÇÒÑ×¼±¸µÄ¶ÓÔ±£¬Ôò¿ÉÒÔ½øÈëÁË
        if askMapID == leaderDataMapID and memPlayerID in memStateDict and memDataMapID != leaderDataMapID:
            resultName = str([askMapID, askMapEx] + enterInfo)
            memPlayer.MapServer_QueryPlayerResult(0, 0, "EnterFBTeamAsk", resultName, len(resultName))
            GameWorld.Log("¶Ó³¤³É¹¦½øÈë×é¶Ó¸±±¾, ¶ÓÔ±¿ªÊ¼½øÈ븱±¾: teamID=%s,memPlayerID=%s" % (teamID, memPlayerID), leader.GetPlayerID())
            
    PyGameData.g_prepareTeamDict.pop(teamID)
    return
def __CheckTeamFBPlayerExist(curTeam):
    ##Íæ¼ÒÀ뿪¸±±¾
    # @param curTeam ¶ÓÎéʵÀý
    # @return ·µ»ØÖµÎÞÒâÒå
    # @remarks Íæ¼ÒÀ뿪¸±±¾, Åж¨ÊÇ·ñ»¹ÓÐÍæ¼ÒÔڴ˸±±¾ÖÐ, Èç¹ûÓÐ, ·µ»Ø, ûÓÐ, ¸Ä¸±±¾IDΪ0
    #Íæ¼ÒÀ뿪¸±±¾, Åж¨ÊÇ·ñ»¹ÓÐÍæ¼ÒÔڴ˸±±¾ÖÐ, Èç¹ûÓÐ, ·µ»Ø, ûÓÐ, ¸Ä¸±±¾IDΪ0
    
    for i in xrange(curTeam.GetMemberCount()):
        curMember = curTeam.GetMemberInfo(i)
        memberPlayer = curMember.GetPlayer()
        if memberPlayer == None:
            continue
        if memberPlayer.GetMapID() == curTeam.GetTeamFBMapID() and memberPlayer.GetFBID() == curTeam.GetTeamFBMapFBID():
            #GameWorld.DebugLog("³ÉÔ±»¹ÔÚÀïÃæ,memID=%s" % memberPlayer.GetPlayerID())
            return True
    return False
##--------------------------------------------
#// B9 10 ²éѯÔÚÏß¶ÓÔ±¶ÔÓ¦¹¦ÄÜÊý¾Ý #tagCGQueryTeamMemFuncData
#
#struct    tagCGQueryTeamMemFuncData
#{
#    tagHead    Head;
#    BYTE    TeamMemFuncType; // ²éѯ¶ÓÔ±µÄ¹¦ÄÜÊý¾ÝÀàÐÍ
#};
def OnQueryTeamMemFuncData(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curTeam = curPlayer.GetTeam()
    if curTeam == None:
        return
    
    teamID = curTeam.GetTeamID()
    queryMemDict = {}
    playerID = curPlayer.GetPlayerID()
    queryFuncType = clientData.TeamMemFuncType
    key = (queryFuncType, teamID, playerID)
    
    for i in xrange(curTeam.GetMemberCount()):
        memPlayer = curTeam.GetMemberPlayer(i)
        #¹ýÂ˲»ÔÚÏߵijÉÔ±
        if memPlayer == None or memPlayer.GetPlayerID() == 0:
            continue
        memMapID = GameWorld.GetQueryPlayerMapID(memPlayer)
        if not memMapID:
            continue
        memPlayerID = memPlayer.GetPlayerID()
        queryMemDict[memPlayerID] = [memMapID, memPlayer.GetRouteServerIndex()]
        
    queryMemIDList = queryMemDict.keys()
    PyGameData.g_queryTeamMemFuncDataDict[key] = [queryMemIDList, {}]
    
    for memPlayerID in queryMemIDList:
        memMapID, routeServerIndex = queryMemDict[memPlayerID]
        sendCMD = str([queryFuncType, teamID, memPlayerID])
        GameWorld.GetPlayerManager().MapServer_QueryPlayer(playerID, 0, memPlayerID, memMapID, "TeamMemFuncData", 
                                                           sendCMD, len(sendCMD), routeServerIndex)
    return
def MapServer_TeamMemFuncData(srcPlayerID, msgList):
    queryFuncType, teamID, memPlayerID = msgList[:3]
    queryFuncRet = str(msgList[3]) if len(msgList) > 3 else ""
    GameWorld.DebugLog("MapServer_TeamMemFuncData srcPlayerID=%s,queryFuncType=%s,teamID=%s,memPlayerID=%s,queryFuncRet=%s" 
                       % (srcPlayerID, queryFuncType, teamID, memPlayerID, queryFuncRet))
    key = (queryFuncType, teamID, srcPlayerID)
    if key not in PyGameData.g_queryTeamMemFuncDataDict:
        return
    queryMemIDList, queryRetDict = PyGameData.g_queryTeamMemFuncDataDict[key]
    queryRetDict[memPlayerID] = queryFuncRet
    
    for memID in queryMemIDList:
        if memID not in queryRetDict:
            #GameWorld.DebugLog("    »¹ÓгÉԱδ»Ø¸´²éѯ½á¹û£¡queryMemIDList=%s" % queryMemIDList)
            return
        
    # ¶¼»Ø¸´ÁË£¬Í¨Öª²éѯµÄÍæ¼Ò
    queryMemIDList, queryRetDict = PyGameData.g_queryTeamMemFuncDataDict.pop(key)
    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
    if not curPlayer:
        return
    GameWorld.DebugLog("Í¨ÖªÍæ¼Ò²éѯ¶ÓÔ±¹¦ÄÜÊý¾Ý½á¹û: queryRetDict=%s" % queryRetDict, srcPlayerID)
    
    memFuncDataPack = ChPyNetSendPack.tagGCTeamMemFuncDataList()
    memFuncDataPack.TeamMemFuncType = queryFuncType
    memFuncDataPack.MemFuncDataList = []
    for memPlayerID, queryFuncRet in queryRetDict.items():
        memFuncData = ChPyNetSendPack.tagGCTeamMemFuncData()
        memFuncData.PlayerID = memPlayerID
        memFuncData.MemFuncData = queryFuncRet
        memFuncData.DataLen = len(memFuncData.MemFuncData)
        memFuncDataPack.MemFuncDataList.append(memFuncData)
    memFuncDataPack.MemCount = len(memFuncDataPack.MemFuncDataList)
    NetPackCommon.SendFakePack(curPlayer, memFuncDataPack)
    return
def DoTeamProcess(tick):
    __PrepareTeamTimeoutLogic(tick)
    return
def __PrepareTeamTimeoutLogic(tick):
    '''×¼±¸¶ÓÎéÒì³£´¦Àí
    ºó¶ËÑÓ³¤15Ã룬·À·¶Ç°¶ËÒì³£Çé¿öµ¼Ö¿¨¶ÓÎé×¼±¸½çÃæ£¬³¬Ê±Ê±Ç¿ÖÆÈ¡Ïû×¼±¸¶ÓÎé
    '''
    if PyGameData.g_teamFBEnterAskDict:
        for teamID, askInfo in PyGameData.g_teamFBEnterAskDict.items():
            if askInfo:
                askVer, askType, askMapID, askMapEx, askPlayerRetDict, askTick = askInfo
                # ѯÎʵÄ×ö¸ö10sÔ¤·À£¬³¬Ê±µÄ»°ÒƳý
                if tick - askTick <= 10000:
                    continue
            PyGameData.g_teamFBEnterAskDict.pop(teamID)
            GameWorld.ErrLog("¶ÓÎé½øÈ븱±¾Ñ¯Îʳ¬Ê±£¬Ç¿ÖÆÒƳýѯÎÊ״̬! teamID=%s,askVer=%s,askType=%s,askMapID=%s,askMapEx=%s,askPlayerRetDict=%s,askTick=%s,tick=%s" 
                             % (teamID, askVer, askType, askMapID, askMapEx, askPlayerRetDict, askTick, tick))
            
    if not PyGameData.g_prepareTeamDict:
        return
    
    teamMgr = GameWorld.GetTeamManager()
    TeamReadyTime = IpyGameDataPY.GetFuncCfg("TeamReadyTime", 1)
    TeamReadyTime = (TeamReadyTime + 15) * 1000
    for teamID, prepareInfo in PyGameData.g_prepareTeamDict.items():
        askMapID, askMapEx, memStateDict, startTick = prepareInfo
        if tick - startTick <= TeamReadyTime:
            continue
        
        PyGameData.g_prepareTeamDict.pop(teamID)
        GameWorld.ErrLog("¶ÓÎé×¼±¸³¬Ê±£¬Ç¿Öƽâ³ý¶ÓÎé×¼±¸×´Ì¬! teamID=%s,askMapID=%s,askMapEx=%s,memStateDict=%s,startTick=%s,tick=%s" 
                         % (teamID, askMapID, askMapEx, memStateDict, startTick, tick))
        curTeam = teamMgr.FindTeam(teamID)
        if curTeam:
            SyncTeamEnterFBPrepareInfo(curTeam, askMapID, askMapEx, memStateDict, True)
    return
#// B9 0A °´Ìõ¼þÑûÇëÍæ¼Ò¼ÓÈë¶ÓÎé #tagCGInvitePlayerJoinTeamByLV
#
#struct    tagCGInvitePlayerJoinTeamByLV
#{
#    tagHead        Head;
#    WORD        LVLimit;        // Ä¿±êÍæ¼Ò´óÓÚµÈÓڴ˵ȼ¶
#    BYTE        InviteCnt;    // ÑûÇëÍæ¼Ò¸öÊý
#};
def OnInvitePlayerJoinTeamByLV(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    lvlimit = clientData.LVLimit
    inviteCnt = clientData.InviteCnt
    
    curPlayerTeam = curPlayer.GetTeam()
    if not curPlayerTeam:
        return
    curInviteCnt = 0 #µ±Ç°ÑûÇëÊýÁ¿
    playerManager = GameWorld.GetPlayerManager()
    playerCount = playerManager.GetActivePlayerCount()
    if playerCount < 2:
        return
    indexList = range(playerCount)
    random.shuffle(indexList)
    for i in indexList:
        tagPlayer = playerManager.GetActivePlayerAt(i)
        if tagPlayer == None or not tagPlayer.GetInitOK():
            continue
        if PlayerControl.GetIsTJG(tagPlayer):
            continue
        if tagPlayer.GetPlayerID() == curPlayer.GetPlayerID():
            continue
        if tagPlayer.GetLV() < lvlimit:
            continue
        if tagPlayer.GetTeam():
            continue
        if InvitePlayerJoinTeamReq(curPlayer, tagPlayer, curPlayerTeam, tick):
            curInviteCnt +=1
        if curInviteCnt >= inviteCnt:
            break
        
    return
def DR_Team(eventName, teamID, dataDict):
    drDict = {"EventName":eventName, "TeamID":teamID}
    drDict.update(dataDict)
    DataRecordPack.SendEventPack("Team_GameServer", drDict)
    return