using System.Collections.Generic;
using Games.GlobeDefine;
using Games.Scene;
using GCGame.Table;
using Module.Log;
using UnityEngine;
using UnityEngine.AI;

namespace Games.LogicObj
{
    public partial class Obj_MainPlayer
    {
        public static int fubenId
        {
            get { return GameManager.gameManager.PlayerDataPool.EnterSceneCache.EnterCopySceneID; }
        }

        // 队员距离队长超过这个距离就开始骑马
        private const float _mountDistance = 15f;
        // 队员最大传送时间
        private const float _maxMemberTeleportTime = 5f;

        // 组队跟随状态更新
        private const float _updateFollowInterval = 0.2f;

        // 组队跟随位置差值
        private const float _followDistance = 1.5f;

        // 模拟器在Obj存在时允许的偏差量
        private const float _objSimulatorDiffer = 3f;

        // 模拟器最大偏移量 - 同实际角色偏差超过这个数值,就补正位置
        private const float _maxSimulatorDiffer = 5f;

        // 预测队员移动距离的参数
        private const float _updateFollowPredictTime = 0.3f;

        // 组队跳跃容忍误差
        private const float _jumpSimulatorDiffer = 1f;

        // 队员进入自动战斗的距离
        public const float memberEnterAutoCombatDistance = (GlobeVar.MAX_TEAM_MEMBER - 1) * _followDistance + 4f;

        // 队员离开自动战斗的距离
        public const float memberLeaveAutoCombatDistance = memberEnterAutoCombatDistance + 15f;

        // 队长路径。注:队长保持这个路径更新,即使没有玩家处于组队跟随状态
        private readonly List<Vector3> _leaderPosList = new List<Vector3>(GlobeVar.MAX_TEAM_MEMBER);

        // 上次切换跟随状态时间
        private float _enterFollowTime;

        private float _nextUpdateFollowTime;

        // 结束组队跟随时,是否进入自动战斗
        public bool debugTeamTeleport;

        public List<TeamMemberMoveSimulator> moveSimulatorList = new List<TeamMemberMoveSimulator>();

        /// <summary>
        ///     检查主角是否处于组队跟随状态
        /// </summary>
        public bool IsFollowTeam
        {
            get { return GameManager.gameManager.PlayerDataPool.IsFollowTeam; }
        }

        public int FollowState
        {
            get { return GameManager.gameManager.PlayerDataPool.TeamInfo.GetFollowState(); }
        }

        public int sceneAutoType
        {
            get
            {
                if (_sceneAutoType == null)
                    _sceneAutoType = CommonUtility.FubenAutoType();
                return _sceneAutoType.Value;
            }
        }

        private int? _sceneAutoType;
        //邀请某个玩家入队
        public void ReqInviteTeam(ulong playerGuid)
        {
            //检查被邀请者GUID是否为空(由于可以创建单人队伍,所以发空guid说明是单人组队,可以认为合法)
            //if (GlobeVar.INVALID_GUID == playerGuid)
            //{
            //    return;
            //}

            //判断队伍是否已满
            if (GameManager.gameManager.PlayerDataPool.IsHaveTeam())
                if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsFull())
                    SendNoticMsg(false, "#{1145}");

            //非单人组队,增加提示“邀请已发送”
            //if (playerGuid != GlobeVar.INVALID_GUID)
            //{
            //    SendNoticMsg(false, "#{3170}");
            //}

            //向服务器发送邀请某人加入队伍消息
            var msg = (CG_REQ_TEAM_INVITE) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_TEAM_INVITE);
            msg.Guid = playerGuid;
            msg.SendPacket();
        }

        //申请加入队伍
        public void ReqJoinTeam(int teamId)
        {
            //if (teamID <= 0)
            //{
            //    GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#5141}"));
            //    return;
            //}

            //有队伍则不得申请
            if (GameManager.gameManager.PlayerDataPool.IsHaveTeam())
            {
                if (teamId == GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID)
                    return;
                //SendNoticMsg(false, "#{2179}");
                MessageBoxLogic.OpenOKCancelBox(StrDictionary.GetClientDictionaryString("#{4605}"), "",
                    ReqJoinLeaveOldOK, ReqJoinLeaveOldCancel);
                return;
            }

            //GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#5142}"));
            //向服务器发送申请加入队伍消息
            var msg = (CG_REQ_TEAM_JOIN) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_TEAM_JOIN);
            msg.Teamid = teamId;
            msg.SendPacket();
        }

        public void ReqJoinLeaveOldOK()
        {
            var msg = (CG_REQ_TEAM_LEAVE) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_TEAM_LEAVE);
            msg.TeamID = GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID;
            //msg.NewTeamMember = m_NewTeamMemberBuffer;
            msg.SendPacket();
        }

        public void ReqJoinLeaveOldCancel()
        {
        }

        //申请离开队伍
        public void ReqLeaveTeam()
        {
            //向服务器发送申请离队消息
            var msg = (CG_REQ_TEAM_LEAVE) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_TEAM_LEAVE);
            msg.SetTeamID(GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID);
            msg.SendPacket();
        }

        //申请踢人
        public void ReqKickTeamMember(ulong teamMemberGuid)
        {
            if (GlobeVar.INVALID_GUID == teamMemberGuid)
                return;

            var msg = (CG_REQ_TEAM_KICK_MEMBER) PacketDistributed.CreatePacket(MessageID
                .PACKET_CG_REQ_TEAM_KICK_MEMBER);
            msg.SetTeamMemberGuid(teamMemberGuid);
            msg.SendPacket();
        }

        //申请变换队长
        public void ReqChangeTeamLeader(ulong teamMemberGuid)
        {
            if (GlobeVar.INVALID_GUID == teamMemberGuid)
                return;

            var msg = (CG_REQ_TEAM_CHANGE_LEADER) PacketDistributed.CreatePacket(MessageID
                .PACKET_CG_REQ_TEAM_CHANGE_LEADER);
            msg.SetTeamMemberGuid(teamMemberGuid);
            msg.SendPacket();
        }

        //更新某个组员信息,第三位为是否只更新HP标记
        public void UpdateTeamMemberInfo(int nIndex, GC_TEAM_SYNC_MEMBERINFO packet)
        {
            //下标判断
            if (nIndex < 0 || nIndex >= GlobeVar.MAX_TEAM_MEMBER)
                return;

            //更新数据
            GameManager.gameManager.PlayerDataPool.TeamInfo.UpdateMember(nIndex, packet);

            //更新UI数据
            if (TeamList.Instance() == null)
                return;
            TeamList.Instance().UpdateTeamMember();
        }

        //收到离开队伍消息
        public void LeaveTeam()
        {
            //清理队伍数据
            GameManager.gameManager.PlayerDataPool.TeamInfo.CleanUp();

            //通知UI清理队伍数据
            TeamList.Instance().ClearTeamListUI();

            //更新队长头像
            if (null != PlayerFrameLogic.Instance())
            {
                //PlayerFrameLogic.Instance().SetTeamCaptain(false);
            }

            //退出组队跟随状态
            LeaveTeamFollow();
        }

        //MainPlayer是否为队长
        public bool IsTeamLeader()
        {
            if (GlobeVar.INVALID_ID == GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID)
                return false;

            return GUID == GameManager.gameManager.PlayerDataPool.TeamInfo.GetTeamMember(0).Guid;
        }

        //否个Guid是否为队长
        public bool IsTeamLeader(ulong guid)
        {
            if (GlobeVar.INVALID_ID == GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID ||
                GlobeVar.INVALID_GUID == guid)
                return false;
            return guid == GameManager.gameManager.PlayerDataPool.TeamInfo.GetTeamMember(0).Guid;
        }

        public void EnterTeamFollow()
        {
            //没有队伍,无法进入组队跟随状态
            if (GlobeVar.INVALID_ID == GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID)
                return;

            if (Singleton<ObjManager>.Instance.MainPlayer.IsInPaoShang() &&
                !GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain())
            {
                GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#34007}"));
                return;
            }

            //BOSS之家的判断
            //if (InHomeBoss())
            //    return;

            SetTeamFollowState(TeamFollowState.followMove);
        }

        //跟随进入BOSS之家时需要判断队员是否都满足条件
        private bool InHomeBoss()
        {
            if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain() == false)
            {
                TeamMember captain = GameManager.gameManager.PlayerDataPool.TeamInfo.GetTeamMember(0);
                if (captain.IsValid() == false)
                    return false;
                if (WorldBossData.Instance.IsInHomeBossFuben(captain.SceneClassID) == false)
                    return false;
                int sceneVipLevel = WorldBossData.Instance.SceneVipLevel(captain.SceneClassID);
                if (sceneVipLevel > WorldBossData.Instance.VipCanUseLevel)
                {
                    GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#49152}",GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.RoleName, sceneVipLevel));
                }
            }
            else
            {
                if (WorldBossData.Instance.IsInHomeBossFuben(GameManager.gameManager.RunningScene) == false)
                    return false;
                int sceneVipLevel = WorldBossData.Instance.SceneVipLevel(GameManager.gameManager.RunningScene);
                for (var i = 1; i < GlobeVar.MAX_TEAM_MEMBER; i++)
                {
                    TeamMember member = GameManager.gameManager.PlayerDataPool.TeamInfo.GetTeamMember(i);
                    if (member.IsValid() == false)
                        continue;
                    if (WorldBossData.Instance.IsInHomeBossFuben(member.SceneClassID) == false)
                        continue;
                    if (sceneVipLevel > 0)
                    {
                        GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#49152}", member.MemberName, sceneVipLevel));
                    }
                }
            }

            return true;
        }

        public void TeamEnterAutoCombat()
        {
            SetTeamFollowState(TeamFollowState.followCombat);
        }

        public void TeamLeaderEndCombat()
        {
            var teamMembers = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember;
            for (var i = 1; i < teamMembers.Length; i++)
                if (teamMembers[i].IsValid())
                {
                    if (teamMembers[i].FollowState == TeamFollowState.followCombat)
                        SetTeamFollowState(TeamFollowState.followMove, teamMembers[i].Guid);
                }
                else
                {
                    break;
                }
        }

        public void BreakTeamTeleport()
        {
            if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain())
            {
                var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
                if (leader.IsValid())
                {
                    leader.teleportFreezeTime = 0f;
                    for (var i = 1; i < GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Length; ++i)
                    {
                        var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[i];
                        if (member.FollowLeader())
                            TryMatchSceneWithLeader(member, leader);
                    }
                }
            }
        }

        //结束组队跟随状态
        public void LeaveTeamFollow()
        {
            SetTeamFollowState(TeamFollowState.notFollow);
        }

        private void SetTeamFollowState(int followState, ulong? guid = null)
        {
            if (guid == null)
                guid = GUID;
            var packet =
                (CG_REQ_CHANGE_TEAM_MEMBER_FOLLOWSTATE) PacketDistributed.CreatePacket(MessageID
                    .PACKET_CG_REQ_CHANGE_TEAM_MEMBER_FOLLOWSTATE);
            packet.SetOpguid(guid.Value);
            packet.SetFollowstate(followState);
            packet.SendPacket();
        }

        /// <summary>
        ///     主角在进入一个新场景时,试图根据当前场景配置自动战斗情况
        /// </summary>
        public void RefreshPlayerAutoCombat()
        {
            var autoType =
                CommonUtility.FubenAutoType(GameManager.gameManager.PlayerDataPool.EnterSceneCache.EnterCopySceneID);
            // 是否执行组队队员更新策略
            var teamMemberUpdate = false;
            if (GameManager.gameManager.PlayerDataPool.IsHaveTeam())
                if (!GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain())
                    teamMemberUpdate = true;
            if (autoType == FubenAutoType.auto)
            {
                if (!isAutoCombat)
                {
                    if (LoadingWindow._IsLoadingScene)
                        EnterAutoCombatAfterLoading();
                    else
                        EnterAutoCombat();
                }
            }
            else
            {
                LeveAutoCombat();
            }

            if (teamMemberUpdate)
            {
                if (autoType == FubenAutoType.noAuto)
                {
                    var lastFuben = GameManager.gameManager.PlayerDataPool.EnterSceneCache.LastFuben;
                    // 如果副本为退出后跟随副本,则进入跟随状态
                    if (lastFuben != null && lastFuben.FollowAfterQuit > 0)
                        SetTeamFollowState(TeamFollowState.followMove);
                }
                else
                {
                    SetTeamFollowState(TeamFollowState.notFollow);
                }
            }
        }

        /// <summary>
        ///     试图让队员传送到队长的场景
        /// </summary>
        /// <returns>队员是否处于传送中</returns>
        // 注:这个函数仅仅允许队长调用,队员调用会出错
        private bool TryMatchSceneWithLeader(TeamMember member, TeamMember leader)
        {
            var result = false;
            // 队长处于传送状态,不发送消息
            if (leader.teleportFreezeTime > Time.realtimeSinceStartup)
            {
                result = true;
            }
            // 队员处于传送状态,不接受新的传送指令
            else if (member.teleportFreezeTime > Time.realtimeSinceStartup)
            {
                // 队长不传送,队员和队长在同一场景时,取消传送
                result = member.SceneClassID != fubenId || member.SceneInstID != SceneData.SceneInst;
            }
            // 队长不处于副本场景中
            else if (member.SceneClassID != fubenId)
            {
                if (AllowCallIn(fubenId, member.SceneClassID))
                {
                    StartTeleportProcess(member, fubenId, leader.SceneInstID);
                    result = true;
                }
            }
            else if (member.SceneInstID != SceneData.SceneInst)
            {
                if (AllowCallIn(fubenId, member.SceneClassID))
                {
                    StartInstProcess(member, SceneData.SceneInst);
                    result = true;
                }
            }

            return result;
        }

        public static bool AllowCallIn(int leaderSceneId, int memberSceneId)
        {
            return AllowCallIn(leaderSceneId) && AllowCallIn(memberSceneId);
        }

        private static bool AllowCallIn(int fubenId)
        {
            var result = true;
            var fuben = TableManager.GetFubenByID(fubenId, 0);
            if (fuben != null)
                result = fuben.Type < 2 || fuben.CallTeam > 0;
            return result;
        }


        /// <summary>
        ///     开始传送到队长所在场景
        /// </summary>
        // 注:这一套流程只允许队长执行,非队长执行将会导致问题
        private void StartTeleportProcess(TeamMember member, int fubenId, int sceneInst)
        {
            if (debugTeamTeleport)
            {
                LogModule.DebugLog(string.Format("Teleport Scene {0} Inst {1}", fubenId, sceneInst));
                LogModule.DebugLog(string.Format("Member Scene {0} Inst {1}", member.SceneClassID, member.SceneInstID));
                LogModule.WarningLog("Teleport Start");
            }

            // 确保都转入组队移动状态
            if (member.FollowState != TeamFollowState.followMove)
                SetTeamFollowState(TeamFollowState.followMove);
            var packet =
                (CG_REQ_MEMBER_CHANGE_SCENE) PacketDistributed.CreatePacket(MessageID
                    .PACKET_CG_REQ_MEMBER_CHANGE_SCENE);
            packet.SetMemberguid((long) member.Guid);
            packet.SetCtype((int) AutoSearchPoint.ChangeMap_Type.WORLDMAP);
            packet.SetTeleportid(-1);
            packet.SetSceneclassid(fubenId);
            packet.SetSceneinstid(sceneInst);
            packet.SetPosX(0);
            packet.SetPosZ(0);
            packet.SendPacket();
            member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
        }

        /// <summary>
        ///     切换到队长世界线
        /// </summary>
        private void StartInstProcess(TeamMember member, int sceneInst)
        {
            if (debugTeamTeleport)
            {
                LogModule.DebugLog(string.Format("Inst Update {0}", sceneInst));
                LogModule.DebugLog(string.Format("Member Scene {0} Inst {1}", member.SceneClassID, member.SceneInstID));
                LogModule.WarningLog("Inst Update Start");
            }

            // 确保都转入组队移动状态
            if (member.FollowState != TeamFollowState.followMove)
                SetTeamFollowState(TeamFollowState.followMove);
            var packet =
                (CG_REQ_MEMBER_SCENE_CHANGEINST) PacketDistributed.CreatePacket(MessageID
                    .PACKET_CG_REQ_MEMBER_SCENE_CHANGEINST);
            packet.SetMemberguid((long) member.Guid);
            packet.SetSceneInst(sceneInst);
            packet.SendPacket();
            member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
        }

        /// <summary>
        ///     玩家试图进入帮会场景
        /// </summary>
        // 同样只有队长调用,非队长调用会出现问题
        // 注:进入帮会由服务器发起,因此不予以处理
        private void TeamEnterGuildMap()
        {
            var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
            if (leader.IsValid())
                leader.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
        }

        // 注:这个方法只能主角队长调用,非主角队长调用会出问题
        // 同TryMatchSceneWithLeader不同,这个传送会限定changeType,teleportId等等参数
        public void TeamChangeSceneFollow(int changeType, int teleportId, int sceneId, int sceneInst, int safeX,
            int safeZ)
        {
            var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
            if (leader.IsValid())
            {
                for (var i = 1; i < GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Length; ++i)
                {
                    var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[i];
                    if (member.FollowLeader())
                    {
                        // 特殊处理:如果队长不处于副本中,
                        if (debugTeamTeleport)
                        {
                            LogModule.DebugLog(string.Format("Teleport Scene {0} Inst {1}", sceneId, sceneInst));
                            LogModule.DebugLog(string.Format("Member Scene {0} Inst {1}", member.SceneClassID,
                                member.SceneInstID));
                            LogModule.WarningLog("Teleport Start");
                        }

                        // 确保都转入组队移动状态
                        //if (member.FollowState != TeamFollowState.followMove)
                        //    SetTeamFollowState(TeamFollowState.followMove);
                        var packet =
                            (CG_REQ_MEMBER_CHANGE_SCENE) PacketDistributed.CreatePacket(MessageID
                                .PACKET_CG_REQ_MEMBER_CHANGE_SCENE);
                        packet.SetMemberguid((long) member.Guid);
                        packet.SetCtype(changeType);
                        packet.SetTeleportid(teleportId);
                        packet.SetSceneclassid(sceneId);
                        packet.SetSceneinstid(sceneInst);
                        packet.SetPosX(safeX);
                        packet.SetPosZ(safeZ);
                        packet.SendPacket();
                        member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
                    }
                }

                leader.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
            }
        }

        // 注:这个方法只能队长调用
        public void TeamChangeInstFollow(int sceneId, int sceneInst)
        {
            var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
            for (var i = 1; i < GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Length; ++i)
            {
                var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[i];
                if (member.FollowLeader() && AllowCallIn(sceneId, member.SceneClassID))
                {
                    if (debugTeamTeleport)
                    {
                        LogModule.DebugLog(string.Format("Teleport Scene {0} Inst {1}", sceneId, sceneInst));
                        LogModule.DebugLog(string.Format("Member Scene {0} Inst {1}", member.SceneClassID,
                            member.SceneInstID));
                        LogModule.WarningLog("Teleport Start");
                    }

                    // 确保都转入组队移动状态
                    if (member.FollowState != TeamFollowState.followMove)
                        SetTeamFollowState(TeamFollowState.followMove);

                    if (member.SceneClassID == sceneId)
                    {
                        if (member.SceneInstID != sceneInst)
                        {
                            var packet =
                                (CG_REQ_MEMBER_SCENE_CHANGEINST) PacketDistributed.CreatePacket(MessageID
                                    .PACKET_CG_REQ_MEMBER_SCENE_CHANGEINST);
                            packet.SetMemberguid((long) member.Guid);
                            packet.SetSceneInst(sceneInst);
                            packet.SendPacket();
                            member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
                        }
                    }
                    else
                    {
                        var packet =
                            (CG_REQ_MEMBER_CHANGE_SCENE) PacketDistributed.CreatePacket(MessageID
                                .PACKET_CG_REQ_MEMBER_CHANGE_SCENE);
                        packet.SetMemberguid((long) member.Guid);
                        packet.SetCtype((int) CG_REQ_CHANGE_SCENE.CHANGETYPE.WORLDMAP);
                        packet.SetTeleportid(-1);
                        packet.SetSceneclassid(sceneId);
                        packet.SetSceneinstid(sceneInst);
                        packet.SetPosX(0);
                        packet.SetPosZ(0);
                        packet.SendPacket();
                        member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
                    }
                }
            }

            leader.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
        }

        public void TeamLeaderRideUpdate()
        {
            var teamMembers = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember;
            for (var i = 0; i < teamMembers.Length; i++)
                teamMembers[i].ridingMatchLead = false;
        }

        /// <summary>
        ///     队员经过跳跃点执行跳跃
        /// </summary>
        public void WrapTeamMember(ulong guid, int jumpId)
        {
            if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain() && guid != GUID)
            {
                var teamMember = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Find(a => a.Guid == guid);
                if (teamMember != null && teamMember.FollowState == TeamFollowState.followMove)
                {
                    var jumpData = TableManager.GetJumpByID(jumpId, 0);
                    float warpTime;
                    jumpData = jumpData.GetFinialJumpData(out warpTime);
                    var position =
                        ActiveScene.GetTerrainPosition(new Vector3(jumpData.EndPosX, Position.y, jumpData.EndPosZ));
                    // Hack:强制处理记录,防止几帧内不同步导致位置回滚,下一次同步位置应该校正到传送后位置
                    teamMember.ScenePos = position.RemoveY();
                    var simulator = GetMoveSimulator(teamMember.Guid);
                    if (simulator != null)
                        simulator.WarpToPosition(teamMember, position, warpTime);
                }
            }
        }

        private TeamMemberMoveSimulator GetMoveSimulator(ulong? guid)
        {
            TeamMemberMoveSimulator result = null;
            for (var i = 0; i < moveSimulatorList.Count; i++)
                if (moveSimulatorList[i].Guid == guid)
                {
                    result = moveSimulatorList[i];
                    break;
                }

            return result;
        }

        private void UpdateTeamFollow()
        {
            // 更新队员跟随位置
            PushLeaderPos(Position);
            if (_nextUpdateFollowTime > Time.unscaledTime || Time.realtimeSinceStartup < AutoSearchAgent.unlockTime)
                return;
            if (GameManager.gameManager == null || !GameManager.gameManager.PlayerDataPool.IsHaveTeam())
                return;
            var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
            if (!leader.IsValid())
                return;
            _nextUpdateFollowTime = Time.unscaledTime + _updateFollowInterval;
            // 队长控制
            if (leader.Guid == ObjManager.Instance.MainPlayer.GUID)
            {
                // 试图为每一个队员预测一个应该走向的位置
                var posIndex = 1;
                for (var i = 1; i < GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Length; i++)
                {
                    var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[i];
                    if (member.IsValid() && member.FollowState != TeamFollowState.notFollow &&
                        !TryMatchSceneWithLeader(member, leader))
                    {
                        // 同队长处于同一场景
                        // Hack: 队长的信息可能会慢一个周期更新,因此暂时处理为直接使用玩家本身的信息
                        if (InTheSameScene(member))
                        {
                            switch (member.FollowState)
                            {
                                case TeamFollowState.followMove:
                                    // 注:如果主角从来没有移动过,仅仅存在Index为0的点
                                    posIndex = Mathf.Min(posIndex, _leaderPosList.Count - 1);
                                    SetTeamMemberPos(member, _leaderPosList[posIndex]);
                                    posIndex++;
                                    // 骑乘状态重置时,执行一次骑乘切换
                                    if (!member.ridingMatchLead)
                                    {
                                        member.ridingMatchLead = true;
                                        SetTeamMemberRide(member, AdcaneMountId >= 0 || (member.ScenePos - leader.ScenePos).sqrMagnitude > _mountDistance.ToSquare());
                                    }
                                    break;
                                case TeamFollowState.followCombat:
                                    if ((member.ScenePos - Position.RemoveY()).sqrMagnitude >
                                        memberLeaveAutoCombatDistance.ToSquare())
                                        SetTeamFollowState(TeamFollowState.followMove, member.Guid);
                                    break;
                            }
                        }
                        // 同队长不在一个场景
                        else
                        {
                            if (member.FollowState == TeamFollowState.followCombat)
                                SetTeamFollowState(TeamFollowState.followMove, member.Guid);
                        }
                    }
                }
                // 试图移除不需要的移动模拟器
                for (var i = moveSimulatorList.Count - 1; i >= 0; i--)
                {
                    var simulator = moveSimulatorList[i];
                    if (simulator.Guid != null)
                    {
                        var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Find(a =>
                            a.Guid == simulator.Guid);
                        if (member == null ||
                            member.FollowState != TeamFollowState.followMove ||
                            !InTheSameScene(member))
                            moveSimulatorList[i].Deactivate();
                    }
                }
            }
        }
        
        private static bool InTheSameScene(TeamMember member)
        {
            return fubenId == member.SceneClassID && SceneData.SceneInst == member.SceneInstID;
        }
        
        private void PushLeaderPos(Vector3 pos)
        {
            // 如果主角处于跳跃和无敌斩状态,不缓存当前位置
            if (MovementState == MoveState.Leap || MovementState == MoveState.OnmiSlash)
                return;
            // 每一米推送一个位置
            if (_leaderPosList.Count == 0 || (_leaderPosList[0] - pos).sqrMagnitude > _followDistance.ToSquare())
            {
                if (_leaderPosList.Count >= GlobeVar.MAX_TEAM_MEMBER)
                    _leaderPosList.RemoveAt(_leaderPosList.Count - 1);
                _leaderPosList.Insert(0, pos);
            }
        }

        private void SetTeamMemberPos(TeamMember teamMember, Vector3 targetPos)
        {
            var simulator = GetMoveSimulator(teamMember.Guid);
            if (simulator == null)
            {
                // 试图重用一个未激活的模拟器
                simulator = GetMoveSimulator(null);
                if (simulator == null)
                {
                    // 构造新的模拟器
                    simulator = new TeamMemberMoveSimulator();
                    moveSimulatorList.Add(simulator);
                }

                simulator.Init(teamMember);
            }

            simulator.MoveToPosition(teamMember, targetPos);
        }

        /// <summary>
        ///     队长起跳时,需要清空跳跃效果
        /// </summary>
        private void UpdatePositionForLeap(Tab_Jump jumpTable)
        {
            jumpTable = jumpTable.GetFinialJumpData();
            _leaderPosList.Clear();
            _leaderPosList.Add(
                ActiveScene.GetTerrainPosition(new Vector3(jumpTable.EndPosX, Position.y, jumpTable.EndPosZ)));
        }

        private void SetTeamMemberRide(TeamMember teamMember, bool isRide)
        {
            if (isRide)
            {
                var packet =
                    (CG_REQ_TEAM_MEMBER_SINGLE_MOUNT) PacketDistributed.CreatePacket(MessageID
                        .PACKET_CG_REQ_TEAM_MEMBER_SINGLE_MOUNT);
                packet.SetMemberguid(teamMember.Guid);
                packet.SendPacket();
            }
        }

        /// <summary>
        ///     队友运动模拟器
        /// </summary>
        // 注:Team里面,队友位置并不满足0.2s内更新,因此只能使用这个组件来进行高精度追踪
        public class TeamMemberMoveSimulator
        {
            private NavMeshAgent _agent;
         
            public ulong? Guid { get; private set; }

            public void Init(TeamMember teamMember)
            {
                Guid = teamMember.Guid;
                var position = GetTeamMemberPos(teamMember);
                var agentName = "TeamMemberSimulator_" + Guid;
                if (_agent == null)
                {
                    var gameObject = new GameObject(agentName);
                    gameObject.transform.position = position;
                    gameObject.transform.rotation = Quaternion.identity;
                    gameObject.transform.localScale = Vector3.one;
                    _agent = gameObject.AddComponent<NavMeshAgent>();
                    SetBasicNavAgentParameter(_agent);
                    SetNavAgentAreaMask(_agent, true);
                    _agent.angularSpeed = 30000f;
                    _agent.speed = teamMember.MoveSpeed;
                }
                else
                {
                    _agent.gameObject.name = agentName;
                    _agent.gameObject.SetActive(true);
                    _agent.ResetPath();
                    _agent.Warp(position);
                }
            }

            private static Vector3 GetTeamMemberPos(TeamMember teamMember)
            {
                var obj = ObjManager.Instance.FindOtherPlayerByGuid(teamMember.Guid);
                var position = obj == null
                    ? ActiveScene.GetTerrainPosition(teamMember.ScenePos.InsertY())
                    : obj.Position;
                return position;
            }

            public void Deactivate()
            {
                Guid = null;
                if (_agent != null)
                {
                    _agent.gameObject.name = "TeamMemberSimulator_Inactive";
                    _agent.gameObject.SetActive(false);
                }
            }

            /// <summary>
            ///     队员经由跳跃点传送到目标位置
            /// </summary>
            public void WarpToPosition(TeamMember teamMember, Vector3 position, float warpTime)
            {
                if (warpTime > 0f)
                    teamMember.warpFreezeTime = Time.unscaledTime + Mathf.Min(_maxMemberTeleportTime, warpTime);
                else
                    teamMember.warpFreezeTime = 0f;
                _agent.Warp(position);
            }

            public void MoveToPosition(TeamMember teamMember, Vector3 position)
            {
                // 动态修改移动速度
                _agent.speed = teamMember.MoveSpeed;
                if (Time.unscaledTime > teamMember.warpFreezeTime)
                {
                    var obj = ObjManager.Instance.FindOtherPlayerByGuid(teamMember.Guid);
                    var sourcePos = obj == null
                        ? ActiveScene.GetTerrainPosition(teamMember.ScenePos.InsertY())
                        : obj.Position;
                    var differDist = obj == null ? _maxSimulatorDiffer : _objSimulatorDiffer;
                    // 角色距离差值超过容忍范围
                    if ((sourcePos.RemoveY() - _agent.transform.position.RemoveY()).sqrMagnitude >
                        differDist.ToSquare())
                    {
                        LogModule.WarningLog(string.Format("Team Member {0}, Pos {1} is too far from {2}", teamMember.Guid,
                            _agent.transform.position.ToPreciseString(),
                            sourcePos.ToPreciseString()));
                        _agent.Warp(sourcePos);
                        teamMember.warpFreezeTime = 0f;
                    }
                    // 特殊处理跳跃等待情况,防止预测机锁死在OffmeshLink
                    if (!_agent.isOnOffMeshLink)
                    {
                        if (!_agent.isOnNavMesh)
                            _agent.Warp(sourcePos);
                        if (_agent.isOnNavMesh)
                        {
                            var path = _agent.path;
                            if ((position - _agent.transform.position).RemoveY().sqrMagnitude >
                                navAgentPercision.ToSquare())
                            {
                                Vector3 predictPos;
                                if (_agent.CalculatePath(position, path))
                                {
                                    var moveDelta = _agent.speed * _updateFollowPredictTime;
                                    predictPos = path.GetPointOnPath(_agent.transform.position, moveDelta);
                                    _agent.SetPath(path);
                                }
                                else
                                {
                                    _agent.isStopped = true;
                                    predictPos = _agent.transform.position;
                                }

                                // 角色执行常规移动
                                var packet =
                                    (CG_REQ_TEAM_MEMBER_MOVE) PacketDistributed.CreatePacket(MessageID
                                        .PACKET_CG_REQ_TEAM_MEMBER_MOVE);
                                packet.SetMemberguid((long) teamMember.Guid);
                                packet.SetPoscount(1);
                                packet.AddPosx(predictPos.x.ToServerPos());
                                packet.AddPosy(predictPos.y.ToServerPos());
                                packet.AddPosz(predictPos.z.ToServerPos());
                                packet.SetIsmoving(1);
                                packet.SendPacket();
                            }
                        }
                        else
                        {
                            LogModule.ErrorLog(string.Format("Cannot fix TeamMember {0} at Pos {1} onto NavMesh at Scene {2}!",
                                teamMember.Guid, teamMember.ScenePos.ToPreciseString(), GameManager.gameManager == null ? "Null" : fubenId.ToString()));
                        }
                    }
                    else
                    {
                        // 非队长移动使用OffmeshLink进行判断
                        // 仅仅在服务器位置处于容错范围内时,才正式开始跳跃;否则呼叫角色走到跳跃点位置
                        if ((teamMember.ScenePos - _agent.transform.position.RemoveY()).sqrMagnitude >
                            _jumpSimulatorDiffer.ToSquare())
                        {
                            var packet =
                                (CG_REQ_TEAM_MEMBER_MOVE) PacketDistributed.CreatePacket(MessageID
                                    .PACKET_CG_REQ_TEAM_MEMBER_MOVE);
                            packet.SetMemberguid((long) teamMember.Guid);
                            packet.SetPoscount(1);
                            packet.AddPosx(_agent.transform.position.x.ToServerPos());
                            packet.AddPosy(_agent.transform.position.y.ToServerPos());
                            packet.AddPosz(_agent.transform.position.z.ToServerPos());
                            packet.SetIsmoving(1);
                            packet.SendPacket();
                        }
                        else
                        {
                            teamMember.warpFreezeTime = Time.unscaledTime + MainPlayerJumpWait.maxWaitTime;
                            var offMeshLink = _agent.currentOffMeshLinkData.offMeshLink;
                            if (offMeshLink != null)
                            {
                                var jumpPoint = offMeshLink.GetComponent<Obj_JumpPoint>();
                                if (jumpPoint != null)
                                {
                                    var jumpProtocol =
                                        (CG_JUMP) PacketDistributed.CreatePacket(MessageID.PACKET_CG_JUMP);
                                    // 注:无视这个警告,Guid不存在时,根本不会更新
                                    jumpProtocol.SetTargetguid(Guid.Value);
                                    jumpProtocol.SetJumpid(jumpPoint.GetJumpId());
                                    jumpProtocol.SetTag(0);
                                    jumpProtocol.SendPacket();
                                    jumpPoint.GetJumpId();
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}