/*
 * 由SharpDevelop创建。
 * 用户： Administrator
 * 日期: 2018-11-16
 * 时间: 9:27
 *
 * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
 */

using GameData;
using Game.Player;
using Game.Robot;
using Game.Shadow;
using GameDAL;
using GameDAL.Backend;
using GameDAL.Game;
using MrWu.Debug;
using ObjectModel.Config;
using ObjectModel.Game;
using Server.Data;
using Server.DB.Redis;
using Server.MQ;
using Server.Pack;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Server.Core;
using zyxAdapter;
using GameMessage.Const;
using GameMessage;
using NetWorkMessage;
using Server.Config;
using Server.Data.Module;
using MessageData = GameData.MessageData;

/*
 * 包明细
 * 玩家信息包
 * 游戏信息包
 * 桌子其他玩家信息包
 * 指令包{
 *   1.上桌
 *   2.重连
 *   3.开战
 *   4.战斗结束
 * }
 *
 * 行为包
 *
 * */

namespace Server
{
    /// <summary>
    /// 游戏管理  单线程操作
    /// </summary>
    public partial class GameManager : IGameUtil, IGameMessage<GamePack>
    {
        /// <summary>
        /// 游戏管理
        /// </summary>
        public static GameManager instance { get; private set; }

        static IHostUtil m_dllUtil;

        /// <summary>
        /// c# 调用子游戏dll的方法
        /// </summary>
        public static IHostUtil dllUtil
        {
            get
            {
                if (m_dllUtil == null)
                {
                    m_dllUtil = instance.factory.CreateHostUtil();
                }

                return m_dllUtil;
            }
        }

        /// <summary>
        /// 游戏配置
        /// </summary>
        public Config.GameConfig config;

        /// <summary>
        /// 游戏单元工厂
        /// </summary>
        public readonly GameUtilFactory factory;

        /// <summary>
        /// 影子管理
        /// </summary>
        public readonly ShadowPool shadowPool;

        #region 房间,厅,桌子相关信息

        /// <summary>
        /// 房间数量
        /// </summary>
        public readonly int roomCnt;

        /// <summary>
        /// 房间
        /// </summary>
        public readonly RoomManager[] rooms;

        /// <summary>
        /// 厅数量
        /// </summary>
        public readonly int tingCnt;

        /// <summary>
        /// 厅-管理桌子控制玩法
        /// </summary>
        private readonly TingManager[] tings;

        /// <summary>
        /// 朋友房厅
        /// </summary>
        public TingManager friendTing
        {
            get
            {
                if (isFriend)
                {
                    return tings[tingCnt - 1];
                }

                return null;
            }
        }

        /// <summary>
        /// 朋友房城堡
        /// </summary>
        public RoomManager friendRoom
        {
            get
            {
                if (isFriend)
                {
                    return rooms[roomCnt - 1];
                }

                return null;
            }
        }

        /// <summary>
        /// 获取所有的桌子
        /// </summary>
        public int deskCnt
        {
            get
            {
                int sum = 0;
                foreach (var item in tings)
                {
                    sum += item.Count;
                }

                return sum;
            }
        }

        /// <summary>
        /// 闲置的桌子数量
        /// </summary>
        public int idleDeskCnt
        {
            get
            {
                int sum = 0;
                foreach (var item in tings)
                {
                    sum += item.IdleCount;
                }

                return sum;
            }
        }

        /// <summary>
        /// 排队中的桌子数量
        /// </summary>
        public int queueDeskCnt
        {
            get
            {
                int sum = 0;
                foreach (var item in tings)
                {
                    sum += item.QueueCount;
                }

                return sum;
            }
        }

        /// <summary>
        /// 开战中的桌子数量
        /// </summary>
        public int warDeskCnt
        {
            get
            {
                int sum = 0;
                foreach (var item in tings)
                {
                    sum += item.WarCount;
                }

                return sum;
            }
        }

        /// <summary>
        /// 开战次数
        /// </summary>
        public int warCnt
        {
            get
            {
                int sum = 0;
                foreach (var item in tings)
                {
                    sum += item.warCnt;
                }

                return sum;
            }
        }

        #endregion

        #region 统计相关信息

        /// <summary>
        /// 消耗的房卡
        /// </summary>
        public int DelFangKa;

        /// <summary>
        /// 登录次数
        /// </summary>
        public long loginCnt { get; set; }

        /// <summary>
        /// 重连次数
        /// </summary>
        public long reConnection { get; protected set; }

        #endregion

        /// <summary>
        /// 不用检查进入房间--测试同桌
        /// </summary>
        public bool noCheckAddDesk;

        /// <summary>
        /// 禁止同桌的玩家
        /// </summary>
        public NoDeskMatesAllowedInfo NoDeskPlayers = new NoDeskMatesAllowedInfo();

        /// <summary>
        /// 充值的商品列表
        /// </summary>
        public List<ChongZhiShangPing> ShangPings = null;

        
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="config">游戏配置</param>
        /// <param name="factory">游戏单元工厂</param>
        public GameManager(Server.Config.GameConfig config, GameUtilFactory factory)
        {
            if (instance == null)
                instance = this; //子类继承了 这个this 就是子类
            this.factory = factory;
            this.config = config;
            shadowPool = factory.GetShadowPool();
            RobotController.instance = new RobotController(this, ServerConfigManager.Instance.RobotMinMoney, ServerConfigManager.Instance.RobotMaxMoney);

            //PlayerCollection.instance = new PlayerCollection(config.maxPlayer);

            int len = ServerConfigManager.Instance.Tings.Length;
            tingCnt = len;
            tings = new TingManager[len];

            len = ServerConfigManager.Instance.Castles.Length;
            roomCnt = len;
            rooms = new RoomManager[len];
            GetNoDeskPlayerInfo();

            if (ServerConfigManager.Instance.OpenFriend > 0)
            {
                FightRecordManager.Instance.Init(config.GameId);
            }
            
            GameDispatcher.Instance.AddListener(GameMsgId.UserCurrencyChange,OnCurrencyChange);
        }
        
        /// <summary>
        /// 获取不能同桌的玩家信息
        /// </summary>
        void GetNoDeskPlayerInfo()
        {
            //如果获取不到值就3分钟后再获取
            NoDeskPlayers.GetTime = DateTime.Now.AddMinutes(3);
            //Task.Factory.StartNew(() =>
            //{ //逻辑简单不异步做
            try
            {
                string str = DeskPlayerDal.GetNoDeskPlayer();
                Debug.Info("获取禁止同桌信息：" + str);
                if (!string.IsNullOrWhiteSpace(str))
                {
                    NoDeskPlayers.PlayerIds = JsonPack.GetData<List<NoDeskPlayerInfo>>(str);
                    NoDeskPlayers.GetTime = DateTime.Now.AddMinutes(30);
                }
            }
            catch (Exception e)
            {
                Debug.Error($"获取禁止同桌信息出错 msg:{e.Message} code:{e.StackTrace}");
            }
            //});
        }

        // /// <summary>
        // /// 获取玩家禁止同桌的信息
        // /// </summary>
        // /// <param name="userid"></param>
        // /// <returns>有就返回有的值，没有就是Null</returns>
        // public string GetNoDeskPlayerInfoById(int userid)
        // {
        //     if (userid <= 0) return null;
        //     if (NoDeskPlayers.PlayerIds == null || NoDeskPlayers.PlayerIds.Count <= 0) return null;
        //     string s = userid.ToString();
        //     foreach (var item in NoDeskPlayers.PlayerIds)
        //     {
        //         if (item == null || item.UserIds == null || item.UserIds.Length < 1) continue;
        //         if (item.UserIds.IndexOf(s) >= 0)
        //         {
        //             return item.UserIds;
        //         }
        //     }
        //     return null;
        // }

        #region IGameWinMoney

        /// <summary>
        /// 赢的游戏币
        /// </summary>
        public Int64 winmoney { get; private set; }

        /// <summary>
        /// 税收的游戏币
        /// </summary>
        public Int64 taxmoney { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public void AddWinMoney(long money)
        {
            winmoney += money;
        }

        /// <summary>
        /// 添加税收的钱
        /// </summary>
        /// <param name="money"></param>
        public void AddTaxMoney(long money)
        {
            taxmoney += money;
        }

        #endregion

        #region ITimerProcessor

        /// <summary>
        /// 定时器
        /// </summary>
        public virtual void OnTime(int Interval)
        {
            // if (NoDeskPlayers.GetTime <= DateTime.Now)
            // {
            //     GetNoDeskPlayerInfo();
            // }
            // Debug.Info("GameManager 定时器:" + System.DateTime.Now.Ticks);
            foreach (RoomManager rm in rooms)
            {
                rm.OnTime(Interval);
            }

            foreach (TingManager tm in tings)
            {
                tm.OnTime(Interval);
            }
        }

        /// <summary>
        /// 秒级定时器
        /// </summary>
        public virtual void SecondTime()
        {
            // Debug.Info("秒级定时器:" + System.DateTime.Now.Ticks);
            try
            {
                //var xxx = Debug.StartTiming();
                //SaveClubWarRecordToRedis();
                //double runtimexx = Debug.GetRunTime(xxx);
                // if (runtimexx > 100)
                // {
                //     Debug.Error($"保存数据xxx:{runtimexx}");
                // }
                

                //BisaiManager.instance.SecondTime(); //暂时没有比赛
                foreach (RoomManager rm in rooms)
                {
                    rm.SecondTime();
                }

                foreach (TingManager tm in tings)
                {
                    tm.SecondTime();
                }
            }
            catch (Exception e)
            {
                Debug.Error($"定时器出错,msg:{e.Message},code:{e.StackTrace}");
            }
        }

        public virtual async void DayInit()
        {
            ShangPings = await ChongZhiShangPingDal.GetAllShangPingsAsync();
        }

        #endregion


        #region 查找房间，厅，桌子

        /// <summary>
        /// 是否存在某个房间
        /// </summary>
        /// <param name="roomid">房间id</param>
        /// <returns>true 表示存在房间 false 表示不存在房间</returns>
        public bool isExistsRoom(int roomid)
        {
            return roomid >= 0 && roomid < roomCnt;
        }

        /// <summary>
        /// 获取城堡
        /// </summary>
        /// <param name="roomid"></param>
        /// <returns></returns>
        public RoomManager FindRoom(int roomid)
        {
            if (!isExistsRoom(roomid))
                return null;
            return rooms[roomid];
        }

        /// <summary>
        /// 是否存在某个厅
        /// </summary>
        /// <param name="tingid"></param>
        /// <returns></returns>
        public bool isExistsTing(int tingid)
        {
            return tingid >= 0 && tingid < tingCnt;
        }

        /// <summary>
        /// 查找厅
        /// </summary>
        /// <param name="tingid"></param>
        /// <returns></returns>
        public TingManager FindTing(int tingid)
        {
            if (!isExistsTing(tingid))
                return null;
            return tings[tingid];
        }

        /// <summary>
        /// 获取桌子
        /// </summary>
        /// <param name="tingid">厅id</param>
        /// <param name="deskid">桌子id</param>
        /// <returns>获取桌子</returns>
        public Desk FindDesk(int tingid, int deskid)
        {
            if (!isExistsTing(tingid) || !tings[tingid].isExists(deskid))
            {
                return null;
            }

            return tings[tingid].desks[deskid];
        }

        #endregion

        /// <summary>
        /// Rpc 逻辑
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public virtual bool DoRPC(WaitBeMsg msg)
        {
            switch (msg.head.packlx)
            {
                case ServerPackAgreement.AddPlayerZiChanNum: //给用户加资产信息
                    DoAddPlayerZiChanNum(msg.head, msg.jsondata);
                    break;
                case ServerPackAgreement.RechargeOrders: //处理充值订单
                    
                    break;
                default:
                    Debug.Fatal("未处理的服务器内部消息" + msg.head.packlx);
                    break;
            }

            return true;
        }
        
        /// <summary> 
        /// 给用户加资产信息--目的只是为了同步服务器的内存
        /// </summary>
        /// <param name="head"></param>
        /// <param name="jsondata"></param>
        public virtual void DoAddPlayerZiChanNum(PackHead head, string jsondata)
        {
            if (string.IsNullOrWhiteSpace(jsondata)) return;
            AddZiChanPack data = JsonPack.GetData<AddZiChanPack>(jsondata);
            if (data.datas == null || data.datas.Count <= 0) return;
            foreach (var item in data.datas)
            {
                AddPlayZiChan(item);
            }
        }

        void AddPlayZiChan(AddZiChanInfo data)
        {
            if (data == null || data.UserId <= 0) return;
            Debug.ImportantLog($"收到给玩家加资产包:{data}");
            var pl = PlayerCollection.Instance.FindPlayerByUserId(data.UserId);
            if (pl == null) return;
            switch (data.lx)
            {
                // 类型 1游戏币 2保险柜（*1万） 3参赛卷 4复活卡 5门票 6礼券  7金砖
                case 1:
                    pl.money += data.Num;
                    break;
                case 6:
                    pl.coupon += (int)data.Num;
                    break;
                case 7:
                    pl.MatchRoll += (int)data.Num;
                    break;
                default:
                    Debug.Info($"GameManager 给用户加资产有未处理的类型：{pl.userid} {data.lx}");
                    break;
            }
        }

        private void OnCurrencyChange(object param)
        {
            if (param is UserCurrencyChangeMessage currencyChangeMessage)
            {
                if (currencyChangeMessage.ResDatas == null)
                {
                    Debug.Info("resData is null!");
                    return;
                }
                
                PlayerDataAsyc pl = PlayerCollection.Instance.FindPlayerByUserId(currencyChangeMessage.UserId);
                if (pl == null)
                {
                    Debug.Info($"not find Player:{currencyChangeMessage.UserId}");
                    return;
                }
                
                foreach (var resData in currencyChangeMessage.ResDatas)
                {
                    switch (resData.Id)
                    {
                        case ResName.RoomCard:
                            pl.fangka += (int)resData.Count;
                            break;
                        case ResName.Diamond:
                            pl.MatchRoll += (int)resData.Count;
                            break;
                        case ResName.Gold:
                            pl.money += resData.Count;
                            break;
                        case ResName.Wincoupon:
                            pl.coupon += (int)resData.Count;
                            break;
                        default:
                            Debug.Error($"同步货币数据失败，未知的资源类型:{resData.Id}");
                            break;
                    }
                }
            }
        }

        /// <summary>
        /// 是否写金币扣税日志
        /// </summary>
        /// <param name="pl"></param>
        /// <returns></returns>
        public virtual bool IsWriteKouShuiLog(PlayerDataAsyc pl)
        {
            return true;
        }

        /// <summary>
        /// 收包处理
        /// </summary>
        /// <param name="pk"></param>
        public virtual bool DoPack(GamePack pk)
        {
            //Debug.Info($"收到包类型:{pk.head.packlx}");
            bool doRlt = true;
            switch (pk.Head.packlx)
            {
                case GameSeverAgreement.Login: //玩家登录包
                    if (!LoginManager.Instance.IsCanLogin) //服务器维护，不让登录
                    {
                        //ServerHead head = pk.head;
                        //head.packlx = GamePackAgreement.pack_error;
                        //GameNet.SendPack(pk.head.userid,head,new TipInfo(0,1));
                        //ServerHeadPool.PutServerHead(ref head);
                        return true;
                    }

                    DoLogin(pk);
                    break;

                case GameSeverAgreement.createFriendRoom: //玩家创建房间
                    FriendRoomManager.instance.CreatFriendRoom(pk);
                    break;

                case GameSeverAgreement.joinWay: //快速加入
                    FriendRoomManager.instance.DoWanFa(pk);
                    break;

                case GameSeverAgreement.CreateClubDesk: //创建竞技比赛桌子
                    FriendRoomManager.instance.DoClubCreateDesk(pk);
                    break;

                case GameSeverAgreement.JoinClubDesk: //加入竞技比赛桌子
                    //进入俱乐部桌子
                    FriendRoomManager.instance.JoinClubDesk(pk);
                    break;

                case GameSeverAgreement.ClubDisBankCmd: //会长解散桌子
                    FriendRoomManager.instance.ClubDisBankCmd(pk);
                    break;
                case GameSeverAgreement.ClubMatchDisBankDeskByBurs: //小局结算不够房间最低分，解散桌子
                    Debug.Log("收到小局解散包");
                    FriendRoomManager.instance.ClubMatchDisBankByBurs(pk);
                    break;
                case GameSeverAgreement.ClubOutPlayer: //竞技比赛踢出玩家
                    FriendRoomManager.instance.DoClubOutPlayer(pk);
                    break;
                case GameSeverAgreement.SwitchClubRoom: //切换俱乐部房间
                    FriendRoomManager.instance.QuitGameJoinOther(pk);
                    break;
                /*
                 * 0720 吴补 加入玩法拆分成3个
                 * 1.指定桌子加入房间
                 * 2.创建桌子加入房间
                 * 3.优先加入房间，没有加入再创建桌子加入房间
                 *
                 * */


                case GameSeverAgreement.joinFriendRoom: //玩家加入朋友房
                    FriendRoomManager.instance.DoJoinRoom(pk);
                    break;

                case ServerPackAgreement.DisConnection: //有玩家离线
                    // Debug.Error("接收到玩家离线包!");
                    DisConnection(pk);
                    break;

                case GameSeverAgreement.friendlastInfo: //朋友房上场信息
                    
                    break;

                case GameSeverAgreement.friendfightdata: //回放包
                    FriendRoomManager.instance.DoHuiFang(pk);
                    break;

                case GameSeverAgreement.DeviceInfoPack: //设备信息包
                    DoDeviceInfoPack(pk);
                    break;

                case GameSeverAgreement.outlineGuji: //离线挂机包
                    DoGuaJi(pk);
                    break;
                case GameSeverAgreement.PlayerDePosit: //玩家托管包
                    DoTuoGuan(pk);
                    break;
                //新增竞技比赛主动解散桌子   需要的参数竞技比赛id 玩法id 桌子唯一码



                default:
                    doRlt = false;
                    break;
            }

            if (doRlt)
                return true;

            if (!CheckPack(pk))
                return false;

            switch (pk.Head.packlx)
            {
                
                case GameSeverAgreement.AddBalanceConfig:
                    LuckPlayerManager.Instance.AddBalanceConfig(pk);
                    break;
                case GameSeverAgreement.RemoveBalanceConfig:
                    LuckPlayerManager.Instance.RemoveBalanceConfig(pk);
                    break;
                case GameSeverAgreement.EditorBalanceConfig:
                    LuckPlayerManager.Instance.EditorBalanceConfig(pk);
                    break;
                case GameSeverAgreement.GetBalanceConfigs:
                    LuckPlayerManager.Instance.GetBalanceConfig(pk);
                    break;
                case GameSeverAgreement.AddBalancePlayerConfig:
                    LuckPlayerManager.Instance.AddBalancePlayerConfig(pk);
                    break;
                case GameSeverAgreement.RemoveBalancePlayerConfig:
                    LuckPlayerManager.Instance.RemoveBalancePlayerConfig(pk);
                    break;
                case GameSeverAgreement.EditorBalancePlayerConfig:
                    LuckPlayerManager.Instance.EditorBalancePlayerConfig(pk);
                    break;
                case GameSeverAgreement.GetBalancePlayerConfig:
                    LuckPlayerManager.Instance.GetBalancePlayerConfig(pk);
                    break;
                
                case GameSeverAgreement.AddRoomRateRule:
                    LuckPlayerManager.Instance.AddRoomRateRuleConfig(pk);
                    break;
                case GameSeverAgreement.RemoveRoomRateRule:
                    LuckPlayerManager.Instance.RemoveRoomRateRuleConfig(pk);
                    break;
                case GameSeverAgreement.AddRoomRateRuleItem:
                    LuckPlayerManager.Instance.AddRoomRateRuleItemConfig(pk);
                    break;
                case GameSeverAgreement.RemoveRoomRateRuleItem:
                    LuckPlayerManager.Instance.RemoveRoomRateRuleItemConfig(pk);
                    break;
                
                case GameSeverAgreement.GetRoomRateRuleItem:
                    LuckPlayerManager.Instance.GetRoomRateRuleConfig(pk);
                    break;
                
                
                case GameSeverAgreement.getPlayerData_Test: //获取玩家数据,测试用
                    GameNet.SendPack(pk.pl, pk.Head, pk.pl);
                    break;

                case GameSeverAgreement.InDesk: //上桌包
                    DoInDesk(pk);
                    break;

                case GameSeverAgreement.comBack: //返回
                    DoComBack(pk);
                    break;

                case GameSeverAgreement.readyPk: //准备包
                    ReadyPack(pk);
                    break;

                case GameSeverAgreement.UsingHandTracker: //使用记牌器
                    UsingHandTracker(pk);
                    break;
                
                case GameSeverAgreement.chatDesk: //聊天包
                    DoChatPack(pk);
                    break;

                case GameSeverAgreement.GiveProps: //赠送道具包
                    DoProps(pk);
                    break;

                case GameSeverAgreement.zyxPack: //子游戏包
                    DoZyxPack(pk);
                    break;

                case GameSeverAgreement.Props: //发送道具包
                    break;

                case GameSeverAgreement.dissFriendRoomCmd: //解散房间包
                    FriendRoomManager.instance.DisBankDesk(pk);
                    break;

                case GameSeverAgreement.placedissRoom: //请求解散包
                    FriendRoomManager.instance.placeDisBank(pk);
                    break;

                case GameSeverAgreement.disreponse: //解散回复
                    FriendRoomManager.instance.DisReponse(pk);
                    break;

                case GameSeverAgreement.questOnceFight: //请求立即开战
                    FriendRoomManager.instance.placeOnceFight(pk);
                    break;

                case GameSeverAgreement.voiceData: //语音包
                    _DoVoice(pk);
                    break;

                default:
                    Debug.Error("未解析的包:" + pk.Head.packlx);
                    return false;
            }

            return true;
        }

        #region 登录逻辑

        /// <summary>
        /// 玩家登录收包处理
        /// </summary>
        protected async Task DoLogin(GamePack pack)
        {
            //过滤包,不是本模块处理抛出
            Debug.Info("收到登录包:" + pack.Head.userid);

            DeviceInfo deviceinfo = JsonPack.GetData<DeviceInfo>(pack.JsonData);

            if (deviceinfo == null)
            {
                Debug.Error("登录失败,玩家的设备信息是null");
                return;
            }

            if (string.IsNullOrEmpty(pack.Head.ip))
            {
                Debug.Error("玩家的ip 地址怎么会是空......");
            }

            //var ip = GetNoDeskPlayerInfoById(pack.head.userid);//如果是禁止同桌的人就设置相同Ip

            //Debug.Info("ip:" + ip + "," + pack.head.ip);
            LoginInfo loginInfo = LoginInfo.Create(pack.Head.userid, false, pack.Head.GetUtil(), pack.Head.ip,
                deviceinfo,
                pack.Head.clientVer, pack.Head);
            await LoginManager.Instance.Start(loginInfo);
            loginInfo.Dispose();
        }

        #endregion


        #region 解散房间

        /// <summary>
        /// 处理设备信息包
        /// </summary>
        protected void DoDeviceInfoPack(GamePack pk)
        {
            Debug.Info("接收到设备信息!" + pk.JsonData);

            pk.pl = PlayerCollection.Instance.FindPlayerByUserId(pk.Head.userid);

            if (pk.pl == null)
            {
                //玩家信息为空!
                Debug.Warning("收到设备信息包,玩家数据为空!" + pk.Head.userid);
                return;
            }

            DeviceInfo info = JsonPack.GetData<DeviceInfo>(pk.JsonData);

            var pl = pk.pl;
            //更新设备信息
            pl.UpdateDeviceInfo(info);

            var desk = FindDesk(pl.tingid, pl.deskid);
            if (desk != null)
            {
                //有桌子则更新 没桌子不处理
                desk.ChangePosition();
            }
        }

        /// <summary>
        /// 处理离线挂机包
        /// </summary>
        protected void DoGuaJi(GamePack pack)
        {
            int userid = pack.Head.userid;

            PlayerDataAsyc pl = PlayerCollection.Instance.FindPlayerByUserId(userid);
            if (pl == null)
            {
                Debug.Error("处理挂机包时 玩家已离线:" + pl.userid);
            }
            else
            {
                pl.isGuaji = !pl.isGuaji;
            }
        }

        /// <summary>
        /// 语音包
        /// </summary>
        /// <param name="pk"></param>
        protected void _DoVoice(GamePack pk)
        {
            int userid = pk.Head.userid;

            PlayerDataAsyc pl = PlayerCollection.Instance.FindPlayerByUserId(userid);
            if (pl == null)
            {
                Debug.Error("处理语音包时，未找到玩家!");
            }
            else
            {
                var desk = FindDesk(pl.tingid, pl.deskid);

                if (desk == null)
                {
                    Debug.Error("未找到玩家所在的桌子-发送语音失败:" + pl.ToString());
                    return;
                }

                Debug.Info("收到语音包!!!!");
                desk.SendAllPack(pk.Head, pk.JsonData, pl.userid);
            }
        }

        /// <summary>
        /// 玩家网络连接中断处理
        /// </summary>
        /// <param name="pk"></param>
        protected void DisConnection(GamePack pk)
        {
        }

        /// <summary>
        /// 退出房间
        /// </summary>
        /// <param name="pl"></param>
        public virtual bool QuitRoom(PlayerDataAsyc pl)
        {
            //退出房间
            RoomManager room = FindRoom(pl.roomid);
            if (room == null)
            {
                //房间为null
                Debug.Error("数据错误，没找到这个房间!roomid:{0},state:{1},id:{2}", pl.roomid, pl.state, pl.userid);
                return false;
            }
            else
            {
                if (room.Quit(pl))
                {
                    //退出房间!
                    GeneralSendPack.SendSceneChange(pl, SceneType.InGame); //把玩家扔到选城堡
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        #endregion

        /// <summary>
        /// 处理玩家托管逻辑
        /// </summary>
        /// <param name="pl"></param>
        /// <param name="isDeposit">true托管 false取消托管</param>
        public void DoTuoGuanCalc(PlayerDataAsyc pl, bool isDeposit)
        {
            if (pl == null || pl.isRobot) return;

            if (isDeposit)
            {
                //托管
                //托管次数增加 2、记录开始托管时间 
                if (pl.isDePosit)
                {
                    Debug.ImportantLog($"托管中又收到托管包 id:{pl.userid} name:{pl.nickname}");
                }
                else
                {
                    pl.DePositCount++;
                    pl.DePositTime = DateTime.Now;
                }
            }
            else
            {
                //取消托管  //根据开始时间和取消托管的时间来计算托管时长
                if (!pl.isDePosit)
                {
                    Debug.ImportantLog($"是取消托管状态，又取消托管  id:{pl.userid} name:{pl.nickname}");
                }

                if (pl.DePositTime != default(DateTime))
                {
                    pl.DePositSecon += (int)DateTime.Now.Subtract(pl.DePositTime).TotalSeconds;
                    pl.DePositTime = default(DateTime);
                }
            }

            pl.SetDeposit(isDeposit);
            pl.AutoDepositTime = 0;
            Debug.Info($"收到玩家userid：{pl.userid} nickname：{pl.nickname} {(isDeposit ? "托管" : "取消托管")}");
        }

        /// <summary>
        /// 玩家托管
        /// </summary>
        /// <param name="pk">head.otherInt 1托管  2取消托管</param>
        protected virtual void DoTuoGuan(GamePack pk)
        {
            if (pk.Head.otherInt == null || pk.Head.otherInt.Length != 1) return;
            if (pk.pl == null)
                pk.pl = PlayerCollection.Instance.FindPlayerByUserId(pk.Head.userid);
            if (pk.pl == null) return;

            var desk = FindDesk(pk.pl.tingid, pk.pl.deskid);
            if (desk != null && pk.Head.otherInt[0] == 1 && desk.state != DeskState.War)
            {
                return;
            }

            DoTuoGuanCalc(pk.pl, pk.Head.otherInt[0] == 1);
            if (desk != null)
            {
                foreach (var item in desk)
                {
                    if (item == null) continue;
                    if (item.isRobot) continue;
                    desk.SendAllPlayerInfo(item);
                }
                //todo 发送玩家托管状态  上面的发送所有玩家信息可以屏蔽  20250211
                //desk.SendPlayerDePositChange(pk.pl.seat);
            }
        }

        #region 玩家上桌

        /// <summary>
        /// 处理进入桌子
        /// </summary>
        /// <param name="pk"></param>
        protected virtual void DoInDesk(GamePack pk)
        {
            if (pk.pl == null)
            {
                Debug.Error("玩家进入桌子数据错误 pl is null:" + pk.Head.userid);
                return;
            }

            //先判断能不能进入桌子
            InDeskPack idp = JsonPack.GetData<InDeskPack>(pk.JsonData);
            Debug.Info($"原始的房间:{idp.roomid}");
            if (pk.pl.ClientVer < VersionConfigCategory.Instance.CVersion48) //转换成真实的房间id
            {
                idp.roomid = CastleHelper.GetRealCastle(idp.roomid);
                Debug.Info($"转换成真实的房间:{idp.roomid}");
            }
            //int idroom = FindRightRoom(pk.pl.money);
            //Debug.ImportantLog($"idroom:{idroom} idproom{idp.roomid} ");
            //xu添加，如果客户端发送过来的房间ID不合适，就服务器给他找一个合适的房间ID
            idp.roomid = isRightRoom(pk.pl.money, idp.roomid) ? idp.roomid : FindRightRoom(pk.pl.money);
            Debug.Info($"最终计算出正确的房间：{idp.roomid} {pk.pl.money}");
            if (!isExistsRoom(idp.roomid))
            {
                Debug.Warning("Client Pack Error roomCnt:{0},inRoomid:{1}", roomCnt, idp.roomid);
                return;
            }

            //判断玩家游戏币是否超过上限
            if (pk.pl.money < ServerConfigManager.Instance.Castles[idp.roomid].MinMoney)
            {
                Debug.Error($"MinMoney Error:{pk.pl.money} {idp.roomid}");
            }

            RoomManager rm = rooms[idp.roomid];
            rm.InRoom(pk.pl, idp.tingid, idp.deskid);
        }

        /// <summary>
        /// 查找合适的房间
        /// </summary>
        /// <param name="mymoney"></param>
        /// <returns></returns>
        public int FindRightRoom(long mymoney)
        {
            int len = config.OpenFriend > 0 ? ServerConfigManager.Instance.Castles.Length - 2 : ServerConfigManager.Instance.Castles.Length - 1;
            //-2 是去掉一个朋友房
            for (int i = len; i >= 0; i--)
            {
                if (i == len)
                {
                    if (mymoney >= ServerConfigManager.Instance.Castles[i].MinMoney)
                    {
                        return i;
                    }
                }else if (mymoney < ServerConfigManager.Instance.Castles[i].MaxMoney && mymoney >= ServerConfigManager.Instance.Castles[i].MinMoney)
                {
                    return i;
                }
            }

            Debug.Error($"未找到正确的房间 {len}");
            return len; // mymoney > config.castles[len].maxMoney ? len:-1;
        }

        public bool isRightRoom(long mymoney, int roomid)
        {
            if (roomid < 0 || roomid >= ServerConfigManager.Instance.Castles.Length) return false;
            int len = config.OpenFriend > 0 ? ServerConfigManager.Instance.Castles.Length - 2 : ServerConfigManager.Instance.Castles.Length - 1;
            if (roomid > len) return false;
            //最后一个房间
            if (roomid == len && mymoney >= ServerConfigManager.Instance.Castles[roomid].MaxMoney) return true;
            return mymoney < ServerConfigManager.Instance.Castles[roomid].MaxMoney && mymoney >= ServerConfigManager.Instance.Castles[roomid].MinMoney;
        }

        #endregion

        #region 玩家准备

        /// <summary>
        /// 准备
        /// </summary>
        /// <param name="pk"></param>
        protected virtual void ReadyPack(GamePack pk)
        {
            var ting = FindTing(pk.pl.tingid);
            if (ting != null)
                ting.Ready(pk.pl);
            else
                Debug.Warning("玩家准备出错,没有玩家所在的厅:" + pk.pl.tingid);
        }

        #endregion

        /// <summary>
        /// 使用记牌器
        /// </summary>
        /// <param name="pk"></param>
        protected virtual void UsingHandTracker(GamePack pk)
        {
            UsingHandTrackerData pack = MessagePackHelper.Deserialize<UsingHandTrackerData>(pk.Data);
            var ting = FindTing(pk.pl.tingid);
            if (ting != null)
                ting.UsingHandTracker(pk.pl,pack);
            else
                Debug.Warning("玩家准备出错,没有玩家所在的厅:" + pk.pl.tingid);
        }
        
        /// <summary>
        /// 检查包裹的正确性
        /// </summary>
        /// <param name="pk"></param>
        /// <returns></returns>
        protected virtual bool CheckPack(GamePack pk)
        {
            if (pk.Head.packlx != GameSeverAgreement.Login)
            {
                PlayerDataAsyc pl = PlayerCollection.Instance.FindPlayerByUserId(pk.Head.userid);

                if (pl == null)
                {
                    Debug.Error("没找到发包的人:" + pk.Head.packlx + "," + pk.Head.userid);
                    return false;
                }

                if (pl.userid != pk.Head.userid)
                {
                    Debug.Error("userid不对!" + pl.userid + "," + pk.Head.userid);
                    return false;
                }

                if (pl.outline == 1 || pl.state == (int)PlayerState.NOGame)
                {
                    Debug.Warning("玩家没在线!!");
                    return false;
                }

                pk.pl = pl;
                return true;
            }

            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        protected readonly DistributedLock loginLock = new DistributedLock(100);

        private void resumePlayer(PlayerDataAsyc pl)
        {
            long key = Debug.StartTiming();

            var playerData = PlayerFun.GetPlayerData(pl.userid);
            if (playerData != null)
            {
                pl.money = playerData.money + pl.moneyChange;
                pl.fangka = playerData.fangka;
                pl.gold = playerData.gold;
            }

            double runtime = Debug.GetRunTime(key);

            if (runtime > 200)
                Debug.Error("玩家重连，获取玩家数据慢!" + runtime);
        }

        /// <summary>
        /// 玩家重连
        /// </summary>
        /// <param name="pl"></param>
        /// <param name="socket"></param>
        public void Reconnect(PlayerDataAsyc pl, ServerNode socket)
        {
            Debug.Info("重连进入游戏:" + pl.userid);
            reConnection++;

            #region 为重连的玩家更新游戏资产数据 2019/11/10 徐贞卫

            if (pl.userid > 0)
            {
                resumePlayer(pl);
            }

            #endregion
            
            //处理重连
            pl.outline = 0;
            pl.OutLineTime = 0;
            pl.socketUtil = socket;

            GeneralSendPack.SendGameInfo(pl); //游戏信息

            if (pl.deskid >= 0)
            {
                Desk desk = FindDesk(pl.tingid, pl.deskid);

                if (desk == null)
                {
                    Debug.Error("玩家的厅或桌子id 错误:" + pl.tingid + "," + pl.deskid);
                    return;
                }

                if (pl.friendRoomNum > 0)
                {
                    //朋友房发送朋友房信息
                    desk.SendDeskInfo(pl);
                }

                if (pl.shadows == null)
                {
                    if (friendTing == null || friendTing.id != pl.tingid)
                        Debug.Error("玩家在桌上却没有影子:" + pl.userid + "," + pl.deskid
                                    + "," + pl.seat + "," + pl.roomid + "," + pl.tingid + ","
                                    + pl.friendRoomNum + "," + pl.doShadows);
                }

                GeneralSendPack.SendSceneChange(pl, SceneType.Desk); //有桌子进入桌子
                tings[pl.tingid].Reconnect(pl.deskid, pl.seat);
            }
            else
            {
                //Debug.Error($"怎么会没桌子 {pl.userid} {pl.deskid}");
                GeneralSendPack.SendSceneChange(pl, SceneType.InGame); //没桌子就是进入游戏
            }
        }

        /// <summary>
        /// 检查玩家数据是否与数据空中的一致
        /// </summary>
        private void CheckPlayerdata(PlayerDataAsyc pl)
        {
            //验证玩家的游戏币是否与Redis 中的一致

            Thread thread = new Thread(
                () =>
                {
                    var pldata = PlayerFun.GetPlayerData(pl.userid);
                    Debug.ImportantLog("检查玩家数据是否与数据空中的一致 xxuu");
                    if (pldata == null)
                    {
                        Debug.Warning("未取得玩家数据!");
                    }
                    else
                    {
                        if (pl.money != pldata.money || pl.fangka != pldata.fangka || pl.gold != pldata.gold ||
                            pl.coupon != pldata.coupon)
                            Debug.Error("玩家数据与数据库中的值不一致:" + pl.userid + "," + pl.nickname + ",money:" + pl.money
                                        + "," + pldata.money + ",fangka:" + pl.fangka + "," + pldata.fangka + ",gold:" +
                                        pl.gold + "," + pldata.gold
                                        + "coupon:" + pl.coupon + "," + pldata.coupon);
                    }
                }
            );
        }

        /// <summary>
        /// 退出游戏-在线列表中删除
        /// </summary>
        /// <param name="pl"></param>
        /// <param name="tag">标记，哪个入口来的,为了查询问题用</param>
        /// <param name="isSendPack">是否发送场景切换包</param>
        public virtual void QuitGame(PlayerDataAsyc pl, string tag = "", bool isSendPack = true)
        {
            if (pl.isRobot)
            {
                Debug.Error("机器人哪有退出游戏的概念???");
                return;
            }

            if (isSendPack)
            {
                GeneralSendPack.SendSceneChange(pl, SceneType.Main); //把玩家扔到大厅
                Debug.Info("退出游戏发包!");
            }

            if (pl.deskid >= 0)
            {
                Debug.Error("玩家离线时，玩家deskid 还有值:" + pl.userid + "," + pl.deskid + "," + pl.roomid + "," + tag);
            }

            if (pl.state != (int)PlayerState.INGame)
            {
                Debug.Error("玩家离线时,玩家的状态不对:" + pl.userid + "," + pl.state + "," + tag);
            }

            pl.outline = 1;
            pl.OutLineTime = 0;
            //如果这个玩家本来就下线了，那就不执行下面的逻辑
            if (pl.id >= 0 && PlayerCollection.Instance.RemovePlayer(pl) == 1)
            {
                //移除在线玩家
                if (pl.shadowsInfo != null) //退出游戏放回替身
                    shadowPool.PutShadows(pl.shadowsInfo);
                PlayerFun.SavePlayerData(pl.userid);
                if (!PlayerFun.UnLockPlayer(pl.userid, GameBase.instance.myUtil))
                {
                    //解锁玩家
                    Debug.Error("玩家未能正常解锁!" + pl.userid);
                }
                PropManager.Instance.SaveUserPropDataRedis(pl.userid,true);

                //保存玩家输赢战绩
                _ = SaveUserWarDataAsync(pl);

                //TODO 玩家下线行为 上报
                Task.Factory.StartNew(() =>
                {
                    var temp = pl;
                    Debug.ImportantLog($"玩家下线 1 userid:{temp.userid} money:{temp.money}");
                    SaveGameLog(temp);
                });
            }
        }

        private async Task SaveUserWarDataAsync(PlayerDataAsyc pl)
        {
            if (pl.WarData != null)
            {
                UserWarDataModel model = pl.WarData;
                pl.WarData = null;
                await UserWarDataDal.SaveUserWarDataAsync(model).ConfigureAwait(false);
                ReferencePool.Recycle(model);
            }
        }

        public readonly dbbase sqldb = dbbase.gamedb;

        /// <summary>
        /// 保存玩家游戏金钱日志
        /// </summary>
        /// <param name="pl"></param>
        void SaveGameLog(PlayerDataAsyc pl)
        {
            if (pl == null || pl.userid <= 0 || config == null) return;
            if (Math.Abs(pl.WinMoney + pl.BiSiMoney) <= 10000000) return;
            var sql =
                $"insert into sh_log4(userid,money_bak,money_pay,game_id,hjha_loginmoney,hjha_playcount,kxgc_change) values({pl.userid},{(pl.money)},{pl.WinMoney},{config.GameId},{pl.MoneyBak},{pl.Pan},{pl.BiSiMoney})";
            int i = 0;
            try
            {
                i = sqldb.ExecuteNonQuery(sql);
            }
            catch (Exception e)
            {
                Debug.Error($"保存玩家游戏金钱日志 数据出错,sql:{sql} msg:{e.Message}, code:{e.StackTrace}");
            }
        }

        /// <summary>
        /// 玩家离线-只修改状态
        /// </summary>
        /// <param name="pl"></param>
        /// <param name="sendSceneChange">是否发送场景切换包</param>
        public virtual void OutLine(PlayerDataAsyc pl, bool sendSceneChange = true)
        {
            if (sendSceneChange)
                GeneralSendPack.SendSceneChange(pl, SceneType.Main);
            pl.outline = 1;
            pl.OutLineTime = 0;
            pl.socketUtil = null;

            //玩家在桌子上 通知桌子某个玩家掉线了
            var desk = FindDesk(pl.tingid, pl.deskid);
            Debug.Info($"离线离线:{pl.userid}");

            if (desk != null)
            {
                desk.OutLine(pl.seat);
            }
        }

        /// <summary>
        /// 设置玩家影子
        /// </summary>
        /// <param name="pl"></param>
        /// <param name="roomid"></param>
        public bool SetPlayerShadow(PlayerDataAsyc pl, int roomid)
        {
            return shadowPool.SetPlayerShadow(pl, roomid, roomCnt, rooms);
        }

        /// <summary>
        /// 获取有这个厅的房间id
        /// </summary>
        /// <param name="tingid"></param>
        /// <param name="roomid">在哪个房间中找</param>
        /// <returns></returns>
        public int GetTingRoom(int tingid, int roomid = -1)
        {
            if (roomid >= 0)
                return rooms[roomid].isExists(tingid) ? roomid : -1;
            foreach (var rm in rooms)
            {
                if (rooms[rm.id].isExists(tingid))
                    return rm.id;
            }

            return -1;
        }

        /// <summary>
        /// 处理消息数据
        /// </summary>
        /// <param name="head"></param>
        /// <param name="jsondata"></param>
        public virtual void DoMessageData(PackHead head, string jsondata)
        {
            MessageData msgdt = JsonPack.GetData<MessageData>(jsondata);
            if (msgdt.msgStyle == 1)
            {
                //全游戏
                //开一个协程去做
                Debug.Error("未实现对全玩家发送消息");
                //Coroutine.StartCoroutine(DoMessageData(msgdt));
            }
            else if (msgdt.msgStyle == 2)
            {
                //全桌
                PlayerDataAsyc pl = PlayerCollection.Instance.FindPlayerByUserId(msgdt.receiveId);
                if (pl == null) //玩家已经下线
                    return;

                Desk desk = FindDesk(pl.tingid, pl.deskid);
                if (desk != null)
                    desk.DoMessageData(msgdt);
            }
            else
            {
                Debug.Error("类型错误,该消息不是游戏服务器处理:{0}", msgdt.msgStyle);
            }
        }

        #region IGameMessage

        /// <summary>
        /// 处理字游戏包
        /// </summary>
        public virtual void DoZyxPack(GamePack pack)
        {
            //没有厅 不在开战
            if (!isExistsTing(pack.pl.tingid) || pack.pl.state != (int)PlayerState.War)
            {
                Debug.ImportantLog("子游戏收包ting:" + pack.pl.tingid + ",state:" + pack.pl.state + "," + pack.Head.userid +
                                   " len:" + (pack.JsonData == null ? -1 : pack.JsonData.Length));
                return;
            }

            if (config.GameMode == 1)
            {
                //百家乐包
                if (pack.Head.otherInt != null && pack.Head.otherInt.Length > 0)
                {
                    Debug.Log("牛牛包:" + pack.Head.otherInt[0]);
                }
            }

            tings[pack.pl.tingid].DoZyxPack(pack);
        }

        /// <summary>
        /// 处理聊天包
        /// </summary>
        /// <param name="pack"></param>
        public virtual bool DoChatPack(GamePack pack)
        {
            if (!isExistsTing(pack.pl.tingid))
            {
                Debug.Warning("收到聊天包:" + pack.pl.tingid + ",state:" + pack.pl.state);
                return false;
            }

            return tings[pack.pl.tingid].DoChatPack(pack);
        }

        /// <summary>
        /// 处理道具包
        /// </summary>
        /// <param name="pack"></param>
        /// <returns></returns>
        public virtual bool DoProps(GamePack pack)
        {
            if (!isExistsTing(pack.pl.tingid))
            {
                Debug.Warning("收到道具包:" + pack.pl.tingid + ",state:" + pack.pl.state);
                return false;
            }

            return tings[pack.pl.tingid].Drops(pack);
        }

        #endregion


        /// <summary>
        /// 强制结束
        /// </summary>
        /// <param name="userid">强制解散的玩家</param>
        public void ForceOver(int userid)
        {
            PlayerDataAsyc pl = PlayerCollection.Instance.FindPlayerByUserId(userid);
            if (pl == null)
            {
                Debug.Info("无此玩家:{0}", userid);
                return;
            }

            var desk = FindDesk(pl.tingid, pl.deskid);

            if (desk == null)
            {
                Debug.Error("强制结束时，未找到桌子数据:" + pl.ToString());
                return;
            }

            desk.ForceWarOver();
        }

        #region IGameUtil

        /// <summary>
        /// id
        /// </summary>
        int IGameUtil.id
        {
            get { return 0; }
        }

        /// <summary>
        /// 是否是朋友房的游戏
        /// </summary>
        public bool isFriend
        {
            get { return config.OpenFriend == 1; }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            ServerInfoHelper.IsGameServer = true;
            
            //开启朋友房，多创建一个厅
            dllUtil.CreateTing(ServerConfigManager.Instance.Tings.Length, 6);

            CreatTing();

            CreateRoom();

            shadowPool.Init();

            //GetClubWarRecord();

            if (isFriend)
                FriendRoomManager.instance.Init(rooms[roomCnt - 1], tings[tingCnt - 1]);

            void CreatTing()
            {
                int len = tingCnt;
                for (int i = 0; i < len; i++)
                {
                    tings[i] = factory.CreateTing(ServerConfigManager.Instance.Tings[i], isFriend && (i == len - 1)); //开启朋友房，最后一个给朋友房使用
                    tings[i].Init();
                }
            }

            void CreateRoom()
            {
                int len = roomCnt;
                for (int i = 0; i < len; i++)
                {
                    try
                    {
                        CastlesConfig rmConfig = ServerConfigManager.Instance.Castles[i];
                        Debug.Log($" --- :{ServerConfigManager.Instance.Castles.Length} {rooms.Length} {rmConfig.Tings.Length}");
                        rooms[i] = factory.CreateRoom(i, rmConfig, isFriend && (i == len - 1)); //开启朋友房，最后一个给朋友房使用
                        int cnt = rmConfig.Tings.Length;
                        for (int j = 0; j < cnt; j++)
                        {
                            Debug.Log($"得到tingIDs:{rmConfig.Tings[j]} {tings.Length}");
                            rooms[i].AddTing(j, tings[rmConfig.Tings[j]]);
                            rooms[i].Init();
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.Error($"创建房间报错:{e.Message} {i}");
                        throw e;
                    }
                }
            }

            GameDispatcher.Instance.AddListener(GameMsgId.DisConnected, OnDisConnected);
        }

        /// <summary>
        /// 获取整数的数据
        /// </summary>
        /// <param name="lx"></param>
        /// <returns></returns>
        public virtual int GetIntValue(string lx)
        {
            if (lx == null)
                return 0;

            string[] spt = lx.Split('|');

            if (spt.Length <= 0)
                return 0;

            var gmconfig = GameManager.instance.config;

            switch (spt[0])
            {
                case "0": //游戏规则   --游戏通用参数
                    int idx = int.Parse(spt[1]);
                    if (idx < 0 || idx > gmconfig.GameGz.Length)
                        return -1;
                    return gmconfig.GameGz[idx - 1] - 48;
                case "1": //游戏通用设置 暂时废弃
                    break;
                case "2": //是否发布版
                    return 1;
                case "3": //在线玩家数量
                    return PlayerCollection.Instance.PlayerCnt;
                case "4": //窗体是否可见 废弃
                    return 0;
                case "5": //假房间总数 废弃
                    Debug.Error("已经没有假房间了!");
                    break;
                case "6": //私房信息
                    Debug.Error("转到桌子信息!");

                    string lxstr = string.Empty;

                    switch (spt[1])
                    {
                        case "0":
                            Debug.Warning("房间号:" + spt[2] + ",桌号:" + spt[3] + ",获取的数据类型:" + spt[4]);
                            lxstr = spt[4];
                            break;
                        case "1":
                            Debug.Warning("根据时间" + spt[2] + ",房号:" + spt[3] + "，获取的数据类型:" + spt[4]);
                            lxstr = spt[4];
                            break;
                        case "2":
                            Debug.Warning("获取当前桌子的数据类型:" + spt[2]);
                            lxstr = spt[2];
                            break;
                        case "3":
                            Debug.Warning("根据指针获取数据类型:" + spt[3]);
                            lxstr = spt[3];
                            break;
                    }

                    switch (lxstr)
                    {
                        case "0":
                            Debug.Info("获取已完成局数!");
                            break;
                        case "1":
                            Debug.Info("获取当前正在进行的局数(-1)!");
                            break;
                        case "2":
                            Debug.Info("获取朋友房是否是VIP房间!");
                            break;
                        //case "3":

                        //break;
                        case "4":
                            Debug.Info("获取创建的id");
                            break;
                        case "5":
                            Debug.Info("获取总共打多少局!");
                            break;
                        case "6":
                            Debug.Info("获取朋友房是几人的房间!");
                            break;
                        case "7":
                            Debug.Error("获取朋友房的创建类型，这里要非常注意,数据已经改变 原来的定义(0玩家开 1是竞技比赛开 2是代开房间)");
                            break;
                        case "8":
                            Debug.Info(
                                "0默认  -1个人托管[man[x].tuoguan 个人按钮]开启     >0全房托管[配置]开启    tuoguan>0则自动准备（其他子游戏控制）");
                            break;
                    }


                    /*
                     * 0朋友房结束的局数
                     * 1当前是第几局
                     * 2是否是vip
                     * 4创建者id
                     * 5需要打的局数
                     * 6.房间信息
                     * case 2 of
                     * 0: 已完成局数
                     *
                     *
                     *
                     * 7.创建者类型
                     * 8.是否托管
                     *
                     * */

                    break;
                case "7": //游戏版本
                    break;
                case "8": //全服人数
                    break;
                case "44": //服务器是否关闭中
                    break;
                case "444": //服务器是否开启测试
                    break;
            }

            Debug.Error("游戏整数信息未解析，待解析!" + lx);
            return 0;
        }

        /// <summary>
        /// 获取字符串的类型数据
        /// </summary>
        /// <param name="lx"></param>
        /// <returns></returns>
        public virtual string GetStringValue(string lx)
        {
            if (lx == null)
                return string.Empty;

            string[] sqt = lx.Split('|');

            if (sqt.Length <= 0)
            {
                return string.Empty;
            }

            switch (sqt[0])
            {
                case "0": //获取全游戏规则
                    //Debug.Warning("单个规则找厅, 每个厅都是单独分开的!");

                    string allgz = string.Empty;
                    int len = ServerConfigManager.Instance.TingCnt;
                    for (int i = 0; i < len; i++)
                    {
                        allgz += ServerConfigManager.Instance.Tings[i].TingGz;
                    }

                    //Debug.Log(" 读取到所有规则:" + allgz);
                    return allgz;

                case "1": //获取朋友房规则 100个字符串
                    if (sqt.Length < 1)
                    {
                        Debug.Error("获取游戏字符串信息错误:" + lx);
                        break;
                    }

                    switch (sqt[1])
                    {
                        case "0":
                            //看桌子是否是朋友房,是直接拿朋友房规则返回,不是则拼接通用规则与厅规则合成100个字符串返回

                            Debug.Error("根据桌子房间号 与桌子 来包获取朋友房的一百个规则!!!!!", lx[2], lx[3]);
                            break;
                        case "1":


                            Debug.Error("根据房间号根据日期和时间 来包获取朋友房的一百个规则!!!!");
                            break;
                        case "2":

                            //现在没100个了-就只有50个
                            Debug.Error("获取当前桌子的100个规则");
                            break;
                    }

                    break;
            }

            Debug.Error("游戏字符串信息未解析:" + lx);
            return string.Empty;
        }

        /// <summary>
        /// 获取游戏数据
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public virtual object GetData(string tag)
        {
            return null;
        }

        /// <summary>
        /// 关闭服务器执行的代码
        /// </summary>
        public virtual void Close()
        {
            GameDispatcher.Instance.RemoveListener(GameMsgId.DisConnected, OnDisConnected);
            Debug.ImportantLog($"关闭服务器 GameManager!");
            //保存战绩
            _SavePlayerData();
            //SaveClubWarRecord(); //保存俱乐部的战斗数据
            if (rooms != null)
            {
                for (int i = 0; i < tings.Length; i++)
                {
                    tings[i].Close();
                }
            }
        }

        /// <summary>
        /// 保存玩家的战斗数据
        /// </summary>
        void _SavePlayerData()
        {
            var users = PlayerCollection.Instance.GetPlayerUserIds();
            Parallel.ForEach(users, id =>
            {
                if (id <= 0) return;
                var u = PlayerCollection.Instance.FindPlayerByUserId(id);
                CloseServerSavePlayerData(u);
            });
        }

        /// <summary>
        /// 关闭服务器保存玩家数据
        /// </summary>
        /// <param name="u"></param>
        public virtual void CloseServerSavePlayerData(PlayerDataAsyc u)
        {
            if (u == null || u.isRobot) return;
            if (u.WarData != null)
            {
                UserWarDataDal.SaveUserWarData(u.WarData);
            }
        }

        #endregion

        public bool DeleFriendRoom(int roomid, out string msg)
        {
            msg = string.Empty;
            string weiyima2 = string.Empty;
            ServerNode node = new ServerNode();
            if (!GameDAL.FriendRoom.Room.GetWeiyima(roomid, ref weiyima2, ref node))
            {
                msg = "解散失败，桌子不存在！";
                return false;
            }

            if (ServerHeart.instanece.IsDie(node.id, node.nodeNum))
            {
                msg = "解散失败，游戏维护中！";
                return false;
            }

            PackHead head = PackHead.Create();
            head.packlx = node.id * Game.Data.GameData.PackCardInt +
                          GameSeverAgreement.ClubDisBankCmd;
            head.otherString = new string[] { weiyima2 };
            GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head), true);
            head.Dispose();
            return true;
        }
        
        protected virtual void OnDisConnected(object param)
        {
            int userid = (int)param;
            //先看玩家是不是本模块的
            PlayerDataAsyc pl = PlayerCollection.Instance.FindPlayerByUserId(userid);
            if (pl == null)
            {
                //Debug.Error("玩家离线未获取到玩家:" + pk.head.userid);
                return;
            }

            Debug.Info("玩家离线处理-------!" + userid + "," + (pl.socketUtil == null));

            pl.outline = 1;
            pl.OutLineTime = 0;
            if (pl.roomid >= 0)
            {
                //没在房间，直接退出
                RoomManager room = FindRoom(pl.roomid);
                if (room == null)
                {
                    Debug.Error("服务器错误-没有这个房间GameManager:" + pl.roomid);
                    return;
                }
                else
                {
                    if (pl.friendRoomNum <= 0)
                    {
                        if (!room.Quit(pl))
                        {
                            //成功退出的房间
                            OutLine(pl); //没能退出房间,则掉线处理
                            return;
                        }
                    }
                    else
                    {
                        OutLine(pl); //没能退出房间,则掉线处理
                        return;
                    }
                }
            }
            GameManager.instance.QuitGame(pl, "DisConnection", false);
        }


        /// <summary>
        /// 刷新AI榜单
        /// </summary>
        public virtual void RefreshAiBangDan()
        {

        }

        /// <summary>
        /// 刷新比赛机器人
        /// </summary>
        public virtual void RefreshAiRobot()
        {

        }


    }
}