using System.Collections.Generic;
using System.Threading.Tasks;
using GameData;
using Game.Player;
using GameDAL.Backend;
using GameDAL.FriendRoom;
using GameDAL.Game;
using GameMessage;
using MrWu.Debug;
using ObjectModel.Backend;
using ObjectModel.Game;
using Server.Core;
using Server.Data;
using Server.Data.Module;
using Server.Net;

namespace Server
{
    /// <summary>
    /// 肯定是单线程的
    /// </summary>
    public class LoginManager : SingleInstance<LoginManager>
    {
        /// <summary>
        /// 是否允许登录，后续用来做维护限制
        /// </summary>
        public bool IsCanLogin = true;

        public Server.Config.GameConfig Config => ServerConfigManager.Instance.GameConfig;

        public int LoginCnt { get; private set; }

        // <summary>
        /// 锁定的玩家
        /// </summary>
        private static HashSet<int> lockUserIds = new HashSet<int>();

        private void SendInGameInfo(LoginInfo loginInfo, PlayerLockInfo lockInfo)
        {
            if (loginInfo.IsSocket)
            {
                GeneralSendPack.SendInGameInfo(loginInfo.Userid, lockInfo.gameid, Config.GameId,
                    lockInfo.isFriend ? 1 : 0, 2, loginInfo.Socket);
            }
            else
            {
                SendManager.SendInGameInfo_Http(loginInfo.Userid, lockInfo.gameid, Config.GameId,
                    lockInfo.isFriend ? 1 : 0, 2, loginInfo.Head);
            }
        }

        private HashSet<int> LoginTask = new HashSet<int>();
        
        public async Task Start(LoginInfo loginInfo)
        {
            LoginCnt++;

            while (true)
            {
                if (!LoginTask.Contains(loginInfo.Userid))
                {
                    if (!LoginTask.Add(loginInfo.Userid))
                    {
                        Debug.Error("添加登录任务失败！");
                    }
                    else
                    {
                        break;
                    }
                }
                
                await Task.Delay(1);
            }
            
            //获取被锁信息
            var lockInfo = PlayerFun.GetPlayerLockInfo(loginInfo.Userid);

            if (lockInfo != null)
            {
                if (loginInfo.IsTemp)
                {
                    //临时登录，叫玩家直接去那个游戏
                    SendInGameInfo(loginInfo, lockInfo);
                }
                else
                {
                    //正式登录，处理解锁
                    await DealLockInfo(loginInfo, lockInfo);
                }
            }

            if (lockInfo == null || loginInfo.UnLockSuccess)
            {

                Debug.Info("普通登录!!");
                await GeneralLogin(loginInfo);
            }

            if (!LoginTask.Remove(loginInfo.Userid))
            {
                Debug.Error("移除失败!!!!");
            }
        }

        private async Task GeneralLogin(LoginInfo loginInfo)
        {
            Debug.Info($"玩家执行GeneralLogin userid:{loginInfo.Userid}");
            loginInfo.PlayerData = await PlayerFun.GetPlayerDataAsync(loginInfo.Userid);

            if (loginInfo.PlayerData == null)
            {
                //没取到玩家数据,过期重新登录。。。
                GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 1, loginInfo.Socket);
                return;
            }

            //Debug.Info("玩家正常登录!" + userid);
            //没被锁--正常登录
            PlayerDataAsyc mypl = new PlayerDataAsyc(loginInfo.PlayerData);
            
            int addresult = LockAddPlayerList(mypl, loginInfo.IsTemp);
            if (addresult != 1)
            {
                Debug.Error("未正常添加到内存!");
                //未添加到内存,发送提示
                AddPlayerErrorSendPack(loginInfo,addresult);
            }
            else
                LoginOk(loginInfo, mypl, !loginInfo.IsTemp);

            
            loginInfo.Result = addresult == 1;
        }

        private async Task DealLockInfo(LoginInfo loginInfo, PlayerLockInfo lockInfo)
        {
            //锁在别的模块
            if (!lockInfo.util.Equals(GameBase.instance.myUtil))
            {
                UnLockInfoOther(loginInfo, lockInfo);
            }
            else
            {
                //锁在本模块
                await UnLockInfoSelf(loginInfo, lockInfo);
            }
        }

        private async Task UnLockInfoSelf(LoginInfo loginInfo, PlayerLockInfo lockInfo)
        {
            PlayerDataAsyc pl = PlayerCollection.Instance.FindPlayerByUserId(loginInfo.Userid);
            
            if (!lockInfo.isFriend)
            {
                if (DealLockInfoSelfGold(loginInfo, pl))
                {
                    loginInfo.UnLockSuccess = true;
                }

                return;
            }
            else
            {
                await DealLockInfoSelfFriend(loginInfo, pl);
            }
        }

        /// <summary>
        /// 锁定并添加到内存
        /// </summary>
        /// <param name="pl">pl</param>
        /// <param name="isFriend">是否所在朋友房</param>
        /// <returns>1是成功 -1服务器爆满 -2添加失败 -10锁定失败</returns>
        public int LockAddPlayerList(PlayerDataAsyc pl, bool isFriend)
        {
            if (PlayerFun.LockPlayer(pl.userid, GameBase.instance.myUtil, Config.GameId,
                    Config.ClientId, Config.GameName, isFriend))
            {
                //锁定成功
                int result = PlayerCollection.Instance.AddPlayer(pl);
                if (result != 1)
                    PlayerFun.UnLockPlayer(pl.userid, GameBase.instance.myUtil, false);
                return result;
            } //锁定失败

            return -10;
        }

        /// <summary>
        /// 玩家登录完成
        /// </summary>
        /// <param name="pl">玩家</param>
        /// <param name="isSendPack">是否发包</param>
        private void LoginOk(LoginInfo loginInfo, PlayerDataAsyc pl, bool isSendPack, bool isTemp = false,bool isrecover = false)
        {
            pl.gameid = Config.GameId;
            pl.state = (int)PlayerState.INGame;
            if (!isTemp)
            {
                pl.outline = 0;
                pl.OutLineTime = 0;
                pl.socketUtil = loginInfo.Socket;
                pl.ip = loginInfo.IP;
                pl.ClientVer = loginInfo.ClientVer;
            }

            if (!isrecover)
            {
                loginInfo.DeviceInfo.ip = loginInfo.IP;
                pl.UpdateDeviceInfo(loginInfo.DeviceInfo);
            }
            
            pl.MoneyBak = pl.money;
            if (!isTemp && isSendPack)
            {
                GeneralSendPack.SendGameInfo(pl); //游戏信息
                GeneralSendPack.SendSceneChange(pl, SceneType.InGame); //场景切换
                Debug.ImportantLog("登录成功!" + pl.userid + "money:" + pl.money + " platTag:" + pl.platTag +
                                   " regTime:" + pl.RegTime.ToString("yyyy-MM-dd HH:mm:ss"));
            }

            //去拿玩家的推广信息。获取玩家的推广信息如，计算级别
            if (!isTemp && !string.IsNullOrWhiteSpace(pl.platTag))
            {
#if DEBUG
                var user = BMAdminDal.GetBMAdminModelByPlatTag(pl.platTag);
                pl.TuiGuangLeve = (byte)(user == null ? 0 : user.authority == (int)AuthorityType.Person ? 1 : 2);
                pl.TuiGuangUser = user;

#else
                    if (pl.userid < 15274778) //这个userid以前的都不执行推广逻辑
                    {
                        pl.TuiGuangLeve = 0;
                    }
                    else
                    {
                        var user = BMAdminDal.GetBMAdminModelByPlatTag(pl.platTag);
                        pl.TuiGuangLeve =
 (byte)(user == null ? 0 : user.authority == (int)AuthorityType.Person ? 1 : 2);
                        pl.TuiGuangUser = user;
                    }
#endif
                Debug.Info($"name:{pl.nickname} plattag:{pl.platTag} tuigLeve:{pl.TuiGuangLeve} ");
            }

            //加载战绩统计数据
            _ = LoadWarData(pl);

            //进行ip 定位
            if (!isTemp && !string.IsNullOrEmpty(loginInfo.IP) && string.IsNullOrEmpty(pl.device.address))
            {
                IPLocation.UpdateDevice(pl.device, loginInfo.IP);
            }
        }

        private async Task LoadWarData(PlayerDataAsyc pl)
        {
            Debug.Log($"加载WarData {pl.userid}");
            if (Config.OpenGold > 0 && pl.WarData == null)
            {
                UserWarDataModel model = await UserWarDataDal.GetUserWarDataAsync(pl.userid, Config.GameId);
                pl.WarData ??= model;
            }
        }

        //强制玩家离线
        private void SendDisConnection(PlayerDataAsyc pl)
        {
            IUserSession session = GameSessionManager.Instance.FindSession(pl.userid);
            if (session != null)
            {
                session.DisConnected();
            }
            /*
            ServerHead head = new ServerHead();
            head.packlx = ServerPackAgreement.DisConnectionPl;
            head.userid = pl.userid;
            GlobalMQ.instance.DeliveryOne(pl.socketUtil, GlobalMQ.CreateMessage(head, null), true);
            */
        }

        private void ClearRoomNum(LoginInfo loginInfo, PlayerDataAsyc pl)
        {
            Room.ClearPlayerNum(pl.userid);
            if (loginInfo.IsTemp)
            {
                loginInfo.Result = true;
            }
            else
            {
                GameManager.instance.QuitGame(pl, "ClearRoomNum", false);
            }
        }

        //恢复数据
        private bool resumeData(Desk desk, PlayerDataAsyc pl, int userid)
        {
            //加载四个玩家的数据

            //先从deskInfo 中找到 玩家应该在的位置
            int seat = desk.deskinfo.FindPlayer(userid);
            if (seat < 0)
            {
                pl.friendWeiYiMa = null;
                pl.deskid = -1;
                pl.tingid = -1;
                pl.roomid = -1;
                pl.seat = -1;
                pl.state = (int)PlayerState.INGame;
                GameManager.instance.QuitGame(pl, "resumeData");

                Debug.Error($"恢复玩家数据失败，没找到这个玩家的位置:{userid},{desk.deskinfo.roomNum}");
                return false;
            }

            desk.ChangePlayer(seat, pl);
            desk.PlayerChange(pl);

            pl.friendRoomNum = int.Parse(desk.deskinfo.roomNum);
            pl.friendWeiYiMa = desk.deskinfo.weiyima;
            pl.roomid = GameManager.instance.friendRoom.id;
            pl.tingid = GameManager.instance.friendTing.id;
            pl.deskid = desk.id;
            pl.DepositChange = desk.PlayerDepositChange;

            Debug.Info($"恢复玩家数据房间id：{seat} {userid} {pl.roomid} {pl.deskid}");
            if (pl.friendRoomNum <= 0)
            {
                Debug.Error($"恢复玩家数据出错,玩家的房间号错误:{pl.friendRoomNum}");
            }
            else
            {
                Debug.Info($"恢复玩家房间号:{pl.friendRoomNum},{pl.userid}");
            }

            if (!pl.isRobot && pl.roomid >= 0 && pl.roomid < GameManager.instance.roomCnt)
            {
                var room = GameManager.instance.rooms[pl.roomid];
                room.SetRoomPlayerCnt(pl);
            }

            if ((desk.state & DeskState.War) > 0)
                pl.state = (int)PlayerState.War;
            else
                pl.state = (int)PlayerState.Desk;

            if (pl.state == (int)PlayerState.Desk)
            {
                if (desk.deskinfo.noWar)
                {
                    if (desk.deskinfo.rule.RuleEx?.ReadyTimeout > 0)
                        pl.readCtDown = desk.deskinfo.rule.RuleEx.ReadyTimeout;
                    else
                        pl.readCtDown = Config.ClubReadyTimeOut;
                }
                else
                {
                    pl.readCtDown = ServerConfigManager.Instance.FriendAutoReady;
                }

                if (pl.readCtDown <= 0)
                {
                    pl.readCtDown = 1;
                }
            }
            Debug.Info($"恢复玩家，准备时间:{pl.readCtDown}");

            //发包告诉别的玩家用户重连 
            desk.SendAddPlayer(pl);

            Debug.Info($"恢复玩家数据成功！{pl.userid}, deskinfo:{desk.deskinfo.roomNum}");
            return true;
        }
        
        private async Task DealLockInfoSelfFriend(LoginInfo loginInfo, PlayerDataAsyc pl)
        {
            if (pl == null)
            {
                Debug.Log($"DoLockFriend pl is null!{loginInfo.Userid}");
                loginInfo.PlayerData = PlayerFun.GetPlayerData(loginInfo.Userid);

                //没玩家数据,可能服务器重启过,把玩家数据加载到内存中
                //没拿到数据
                if (loginInfo.PlayerData == null)
                {
                    GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 1, loginInfo.Socket);
                    return;
                }

                //添加玩家到内存中
                pl = new PlayerDataAsyc(loginInfo.PlayerData);
                int addresult = PlayerCollection.Instance.AddPlayer(pl);
                if (addresult != 1)
                {
                    AddPlayerErrorSendPack(loginInfo, addresult);
                    return;
                }
                else
                {
                    LoginOk(loginInfo, pl, false);
                    string roomnumstr = string.Empty;
                    string weiyima = string.Empty;

                    if (Room.LoadPlayerNum(loginInfo.Userid, ref roomnumstr, ref weiyima))
                    {
                        pl.friendRoomNum = int.Parse(roomnumstr);
                        pl.friendWeiYiMa = weiyima;
                        Debug.Info("加载房间号:" + pl.friendRoomNum + "," + pl.userid);
                    }
                }
            }

            //看看桌子在不在内存中
            if (string.IsNullOrEmpty(pl.friendWeiYiMa))
            {
                //被锁在朋友房,却没有房间唯一码数据,登录成功
                //临时登录可以认为是登录成功,不是临时登录，应该解锁,用户会以为是卡了,再发起一次就正常
                if (loginInfo.IsTemp)
                {
                    loginInfo.Result = true;
                }
                else
                {
                    GameManager.instance.QuitGame(pl, "DoLockFriend", false);
                }
            }
            else
            {
                //socket 换了, 把之前的Socket 关掉, 启用现在的Socket

                if (!loginInfo.Socket.Equals(pl.socketUtil))
                {
                    if (pl.socketUtil != null)
                    {
                        Debug.Log(
                            $"PlayerSocket:{pl.socketUtil.id} {pl.socketUtil.nodeNum} {loginInfo.Socket.id} {loginInfo.Socket.nodeNum}");
                        if (pl.socketUtil.id != (int)ModuleType.HttpModule)
                        {
                            GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 61, pl.socketUtil);
                            Debug.Warning("用户朋友房多端登录，被挤下线:" + loginInfo.Userid);
                        }
                    }

                    if (loginInfo.IsSocket)
                        pl.socketUtil = loginInfo.Socket;
                }

                //有唯一码数据
                string weiyima = string.Empty;
                ServerNode node = null;
                if (Room.GetWeiyima(pl.friendRoomNum, ref weiyima, ref node))
                {
                    //玩家所在的房间号有唯一码
                    //对比唯一码是否一致
                    if (weiyima == pl.friendWeiYiMa)
                    {
                        //唯一码一致

                        var desk = FriendRoomManager.instance.GetPlayerDesk(pl);

                        Debug.Info($"得到桌子:{desk.GetHashCode()}");
                        if (desk == null)
                        {
                            //未能从数据库中加载到内存
                            ClearRoomNum(loginInfo, pl);
                            return;
                        }

                        //有桌子,且现在玩家数据也在内存中了,把玩家数据赋值到桌子上
                        //把玩家数据赋值到桌子上
                        //这个玩家锁定了等待 
                        if (lockUserIds.Contains(loginInfo.Userid))
                        {
                            Debug.Error($"锁定玩家 !!! {loginInfo.Userid}");
                            while (lockUserIds.Contains(loginInfo.Userid))
                            {
                                await Task.Delay(1);
                            }
                        }

                        if (!desk.Exists(pl.userid))
                        {
                            Debug.Info($"玩家数据不在桌上:{pl.userid} {desk.id} {desk.GetHashCode()}");

                            //玩家数据不在桌上,恢复数据
                            if (!resumeData(desk, pl, loginInfo.Userid)) //未恢复成功就跳走
                                return;

                            for (int i = 0; i < desk.deskinfo.pls.Length; i++)
                            {
                                if (desk.deskinfo.pls[i] == null || desk.deskinfo.pls[i].userid == pl.userid)
                                {
                                    continue;
                                }

                                Debug.Info($"锁定玩家:{desk.deskinfo.pls[i].userid}");
                                lockUserIds.Add(desk.deskinfo.pls[i].userid);
                            }

                            //恢复桌上其他玩家的数据
                            for (int i = 0; i < desk.deskinfo.pls.Length; i++)
                            {
                                if (desk.deskinfo.pls[i] == null || desk.deskinfo.pls[i].userid == pl.userid)
                                {
                                    continue;
                                }

                                PlayerDataAsyc otherPlayer =
                                    PlayerCollection.Instance.FindPlayerByUserId(desk.deskinfo.pls[i].userid);
                                playerData tempPldata = null;
                                if (otherPlayer == null)
                                {
                                    tempPldata = PlayerFun.GetPlayerData(desk.deskinfo.pls[i].userid);
                                }

                                if (otherPlayer == null && tempPldata == null)
                                {
                                    Debug.Error($"恢复其他玩家数据失败!{desk.deskinfo.pls[i].userid}");
                                }
                                else
                                {
                                    //没被锁--正常登录
                                    int addresult = 0;
                                    if (otherPlayer == null)
                                    {
                                        otherPlayer = new PlayerDataAsyc(tempPldata);
                                        addresult = PlayerCollection.Instance.AddPlayer(otherPlayer);
                                    }
                                    else
                                    {
                                        addresult = -2;
                                    }

                                    Debug.Info($"执行恢复其他玩家数据:{otherPlayer.userid} {addresult}");
                                    //添加成功，或者玩家已经存在
                                    if (addresult == 1 || addresult == -2)
                                    {
                                        if (!desk.Exists(otherPlayer.userid))
                                        {
                                            LoginOk(loginInfo,otherPlayer, false, true,true);
                                            resumeData(desk, otherPlayer, otherPlayer.userid);
                                            Debug.Info($"恢复其他玩家:{otherPlayer.userid}!");
                                        }
                                        else
                                        {
                                            Debug.Info($"桌上怎么又玩家了:{otherPlayer.userid}");
                                        }
                                    }
                                    else
                                    {
                                        Debug.Info($"添加到桌子列表失败:{addresult},{otherPlayer.userid}");
                                    }
                                }

                                Debug.Info($"解锁玩家:{desk.deskinfo.pls[i].userid}");
                                lockUserIds.Remove(desk.deskinfo.pls[i].userid);
                            }

                            desk.waitRecover = false;
                            Debug.Info($"恢复桌子成功!{desk.deskinfo.roomNum}");
                            desk.LoadMemSuccess();
                        }

                        Debug.Info($"玩家正常重连! {pl.userid} {loginInfo.ClientVer}");
                        pl.ClientVer = loginInfo.ClientVer;
                        //重连
                        GameManager.instance.Reconnect(pl, loginInfo.Socket);
                        if (!loginInfo.IsTemp)
                        {
                            //正常登陆,那就重连
                            loginInfo.Result = true;
                        }
                    }
                    else
                    {
                        //唯一码不一致 
                        ClearRoomNum(loginInfo, pl);
                    }
                }
                else
                {
                    //玩家所在的房间号没有唯一码,表示玩家所在的房间已被解散 --清楚玩家所在的房间号,并解锁玩家
                    ClearRoomNum(loginInfo, pl);
                }
            }
        }

        /// <summary>
        /// 添加玩家时发生错误发包
        /// </summary>
        /// <param name="loginInfo"></param>
        /// <param name="type"></param>
        private void AddPlayerErrorSendPack(LoginInfo loginInfo, int type)
        {
            switch (type)
            {
                case -1:
                    if (loginInfo.IsSocket)
                        GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 3, loginInfo.Socket);
                    else
                        SendManager.SendErrotInfo_Http(loginInfo.Head, 0, 3);
                    break;
                case -2:
                case -3:
                    Debug.Error("玩家添加到内存时发生错误:" + type);
                    if (loginInfo.IsSocket)
                        GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 13, loginInfo.Socket);
                    else
                        SendManager.SendErrotInfo_Http(loginInfo.Head, 0, 13);
                    break;
                case -10:
                    if (loginInfo.IsSocket)
                        GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 2, loginInfo.Socket);
                    else
                        SendManager.SendErrotInfo_Http(loginInfo.Head, 0, 2);
                    break;
            }
        }

        private bool DealLockInfoSelfGold(LoginInfo loginInfo, PlayerDataAsyc pl)
        {
            if (pl == null)
            {
                Debug.Error($"所在本地，但是没找到玩家! {loginInfo.Userid}");

                if (!PlayerFun.UnLockPlayer(loginInfo.Userid, GameBase.instance.myUtil))
                {
                    Debug.Error($"解锁失败:{loginInfo.Userid}");
                    GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 13, loginInfo.Socket);
                    return false;
                }
                else
                {
                    Debug.Error($"解锁成功-金币场:{loginInfo.Userid}");
                }

                return true;
            }

            if (pl.outline == 0 && !loginInfo.Socket.Equals(pl.socketUtil))
            {
                if (loginInfo.IsTemp)
                {
                    GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 61, loginInfo.Socket);
                    return false;
                }

                GeneralSendPack.SendErrorInfo_Socket(loginInfo.Userid, 0, 61, pl.socketUtil);
                Debug.Error("用户多端登录，被挤下线:" + loginInfo.Userid);
                SendDisConnection(pl);
            }

            //Debug.Error($"未处理解锁:{loginInfo.Userid}");
            GameManager.instance.Reconnect(pl, loginInfo.Socket);
            loginInfo.Result = true;
            return false;
        }

        /// <summary>
        /// 解锁在其他模块中的玩家
        /// </summary>
        /// <param name="loginInfo"></param>
        /// <param name="lockInfo"></param>
        private void UnLockInfoOther(LoginInfo loginInfo, PlayerLockInfo lockInfo)
        {
            if (!TryUnLockPlayer(loginInfo, lockInfo))
            {
                SendInGameInfo(loginInfo, lockInfo);
            }
            else
            {
                loginInfo.UnLockSuccess = true;
            }
        }

        private bool TryUnLockPlayer(LoginInfo loginInfo, PlayerLockInfo lockInfo)
        {
            if (ServerHeart.instanece.IsDie(lockInfo.util.id, lockInfo.util.nodeNum))
            {
                //如果模块已经死亡
                if (PlayerFun.UnLockPlayer(loginInfo.Userid, GameBase.instance.myUtil))
                {
                    //这里只会解锁锁在金币场的游戏
                    return true;
                }
            }

            return false;
        }
    }

    /// <summary>
    /// 登录信息
    /// </summary>
    public class LoginInfo : Reference
    {

        /// <summary>
        /// 登录结果
        /// </summary>
        public bool Result { get; set; }

        /// <summary>
        /// 要登录的Userid
        /// </summary>
        public int Userid { get; private set; }

        /// <summary>
        /// 是否是Socket
        /// </summary>
        public bool IsSocket => Socket != null && Socket.id != (int)ModuleType.HttpModule;

        /// <summary>
        /// 网络收发模块
        /// </summary>
        public ServerNode Socket { get; private set; }

        /// <summary>
        /// 是否是临时登录--
        /// 临时登录的意思表示是玩法加入，或者创建朋友房房间，加入朋友房房间使用的
        /// 因为这些时候是服务器没有玩家的数据，需要登入后才有，得到玩家数据进行处理
        /// 但是临时登录不会发送包裹，比如登录成功发送给玩家游戏数据。
        /// 
        /// </summary>
        public bool IsTemp { get; private set; }

        /// <summary>
        /// ip地址
        /// </summary>
        public string IP { get; private set; }

        /// <summary>
        /// 设备信息
        /// </summary>
        public DeviceInfo DeviceInfo { get; private set; }

        /// <summary>
        /// 客户端版本
        /// </summary>
        public int ClientVer { get; private set; }

        /// <summary>
        /// 包头
        /// </summary>
        public PackHead Head { get; private set; }

        /// <summary>
        /// 解锁是否成功
        /// </summary>
        public bool UnLockSuccess { get; set; }

        public playerData PlayerData { get; set; }

        public static HashSet<int> LockUserIds = new HashSet<int>();

        public static LoginInfo Create(int userid, bool isTemp, ServerNode socket, string ip, DeviceInfo device,
            int clientVer,
            PackHead head)
        {
            LoginInfo loginInfo = ReferencePool.Fetch<LoginInfo>();
            loginInfo.Userid = userid;
            loginInfo.IsTemp = isTemp;
            loginInfo.Socket = socket;
            loginInfo.IP = ip;
            loginInfo.DeviceInfo = device;
            loginInfo.ClientVer = clientVer;
            loginInfo.Head = head;
            loginInfo.UnLockSuccess = false;
            loginInfo.Result = false;
            return loginInfo;
        }

        public override void Dispose()
        {
            Socket = null;
            DeviceInfo = null;
            Head = null;
            PlayerData = null;
            ReferencePool.Recycle(this);
        }
    }
}