| using System;  | 
| using System.Collections.Generic;  | 
| using System.Linq;  | 
|   | 
| using UnityEngine;  | 
| using LitJson;  | 
| using System.Collections;  | 
|   | 
| public class BuyShopItemLimit  | 
| {  | 
|     public uint ItemIndex;  | 
|     public int BuyCnt;        // 今日已购买次数  | 
|     public int isReset;         //是否属于每月重置  0 不重置 1重置  | 
| }  | 
|   | 
| public struct ShopItemInfo  | 
| {  | 
|     public int itemId;  | 
|     public int count;  | 
|   | 
|     public ShopItemInfo(int id, int count)  | 
|     {  | 
|         this.itemId = id;  | 
|         this.count = count;  | 
|     }  | 
| }  | 
|   | 
| public class StoreModel : GameSystemManager<StoreModel>  | 
| {  | 
|   | 
|     public string UNIONSTORESAVE_KEY { get; private set; }  | 
|     public string MUSTBUYSAVE_KEY { get; private set; }  | 
|     public string StoreEffectRecord_Key { get; private set; }  | 
|     public Dictionary<int, Dictionary<int, int>> JobReplaceIdDict = new Dictionary<int, Dictionary<int, int>>();  | 
|     public Dictionary<int, int> showCoinUIDict { get; private set; }  | 
|     public int storeTrailerLv { get; private set; }  | 
|   | 
|   | 
|     public int fairyStoreJumpShopId = 0;  | 
|   | 
|     int m_SelectClassifyId = 0;  | 
|     public int selectSecondType  | 
|     {  | 
|         get { return m_SelectClassifyId; }  | 
|         set  | 
|         {  | 
|             if (m_SelectClassifyId != value)  | 
|             {  | 
|                 m_SelectClassifyId = value;  | 
|                 if (selectClassifyRefresh != null)  | 
|                 {  | 
|                     selectClassifyRefresh();  | 
|                 }  | 
|             }  | 
|         }  | 
|     }  | 
|   | 
|     public event Action selectClassifyRefresh;  | 
|   | 
|   | 
|     private bool isUpdatePlayerLv;  | 
|   | 
|     //排行榜活动的商店  | 
|     public int rankActStore_MoneyType;  | 
|     public int rankActStore_StoreType;  | 
|     public OperationType rankActStore_ActType;  | 
|   | 
|     public override void Init()  | 
|     {  | 
|         ParseFuncConfig();  | 
|         ParseStoreConfig();  | 
|         SetShopRedpoint();  | 
|     }  | 
|   | 
|     public void OnBeforePlayerDataInitialize()  | 
|     {  | 
|         isUpdatePlayerLv = false;  | 
|         IsMustBuyDay = false;  | 
|         sortStoreSecondType = true;  | 
|         ClearJump();  | 
|         FuncOpen.Instance.OnFuncStateChangeEvent -= FuncStateChange;  | 
|         PlayerDatas.Instance.fairyData.OnRefreshFairyMine -= RefreshServerHour;  | 
|         PlayerDatas.Instance.fairyData.OnRefreshFairyInfo -= RefreshFamilyLv;  | 
|         PlayerDatas.Instance.playerDataRefreshEvent -= RefreshPlayerData;  | 
|         TimeMgr.Instance.OnHourEvent -= RefreshServerHour;  | 
|         GlobalTimeEvent.Instance.secondEvent -= UpdateSecond;  | 
|         shopItemlimitDict.Clear();  | 
|         storeFuncType = StoreFunc.DayStore;  | 
|     }  | 
|   | 
|     public void OnAfterPlayerDataInitialize()  | 
|     {  | 
|         UNIONSTORESAVE_KEY = StringUtility.Contact(PlayerDatas.Instance.baseData.PlayerID, LocalSaveStoreType.UnionStore);  | 
|         StoreEffectRecord_Key = StringUtility.Contact(PlayerDatas.Instance.baseData.PlayerID, "StoreEffectRecord");  | 
|         MUSTBUYSAVE_KEY = StringUtility.Contact(PlayerDatas.Instance.baseData.PlayerID, "MustBuy");  | 
|         buyItemCheckDict.Clear();  | 
|     }  | 
|   | 
|     public void OnPlayerLoginOk()  | 
|     {  | 
|         PlayerDatas.Instance.fairyData.OnRefreshFairyInfo += RefreshFamilyLv;  | 
|         PlayerDatas.Instance.fairyData.OnRefreshFairyMine += RefreshServerHour;  | 
|         FuncOpen.Instance.OnFuncStateChangeEvent += FuncStateChange;  | 
|         PlayerDatas.Instance.playerDataRefreshEvent += RefreshPlayerData;  | 
|         TimeMgr.Instance.OnHourEvent += RefreshServerHour;  | 
|         GlobalTimeEvent.Instance.secondEvent += UpdateSecond;  | 
|   | 
|         UpdateShowStore();  | 
|         SetIsMustBuyDay();  | 
|         ControllerRedPoint();  | 
|         UpdateFreeShopRedpoint();  | 
|         UpdateCanBuyRedpoint();  | 
|         UpdateMustBuyRedpoint();  | 
|         UpdateDailyRedpoinit();  | 
|     }  | 
|   | 
|   | 
|   | 
|   | 
|   | 
|     #region 解析本地数据  | 
|     public Dictionary<int, List<int>> storeRedRuleDict { get; private set; } //红点类型 1,免费商品  2,必买商品  3,坐骑灵宠 4,可购买物品(积分兑换)  | 
|     private void ParseFuncConfig()  | 
|     {  | 
|         storeRedRuleDict = new Dictionary<int, List<int>>();  | 
|         FuncConfigConfig storeRedRules = FuncConfigConfig.Get("StoreRedRules");  | 
|         if (storeRedRules != null)  | 
|         {  | 
|             JsonData redRules = JsonMapper.ToObject(storeRedRules.Numerical1);  | 
|             foreach (var type in redRules.Keys)  | 
|             {  | 
|                 int redType = 0;  | 
|                 int.TryParse(type, out redType);  | 
|                 JsonData shops = redRules[type];  | 
|                 if (!storeRedRuleDict.ContainsKey(redType))  | 
|                 {  | 
|                     List<int> shopIdlist = new List<int>();  | 
|                     if (shops.IsArray)  | 
|                     {  | 
|                         for (int i = 0; i < shops.Count; i++)  | 
|                         {  | 
|                             int shopId = 0;  | 
|                             int.TryParse(shops[i].ToString(), out shopId);  | 
|                             shopIdlist.Add(shopId);  | 
|                         }  | 
|                     }  | 
|                     storeRedRuleDict.Add(redType, shopIdlist);  | 
|                 }  | 
|             }  | 
|   | 
|               | 
|         }  | 
|     }  | 
|   | 
|     public Dictionary<int, List<StoreData>> storeTypeDict { get; private set; }  | 
|     public Dictionary<int, List<StoreData>> theOnlyShopDict { get; private set; } //key 物品id  | 
|     public Dictionary<string, List<StoreData>> limitValueShopDict { get; private set; } //key 商品类型和限制条件  | 
|     private void ParseStoreConfig()  | 
|     {  | 
|         storeTypeDict = new Dictionary<int, List<StoreData>>();  | 
|         theOnlyShopDict = new Dictionary<int, List<StoreData>>();  | 
|         limitValueShopDict = new Dictionary<string, List<StoreData>>();  | 
|         List<StoreConfig> storeConfigs = StoreConfig.GetValues();  | 
|         for (int i = 0; i < storeConfigs.Count; i++)  | 
|         {  | 
|             var config = storeConfigs[i];  | 
|             if (config.ShopType != 0)  | 
|             {  | 
|                 StoreData storeData = new StoreData();  | 
|                 storeData.shopId = config.ID;  | 
|                 storeData.storeConfig = config;  | 
|                 storeData.jobReplaceDict = AnalysisJobReplace(config);  | 
|                 if (!storeTypeDict.ContainsKey(config.ShopType))  | 
|                 {  | 
|                     List<StoreData> storeDatas = new List<StoreData>();  | 
|                     storeDatas.Add(storeData);  | 
|                     storeTypeDict.Add(config.ShopType, storeDatas);  | 
|                 }  | 
|                 else  | 
|                 {  | 
|                     storeTypeDict[config.ShopType].Add(storeData);  | 
|                 }  | 
|   | 
|                 if (config.TheOnlyShop == 1)  | 
|                 {  | 
|                     if (!theOnlyShopDict.ContainsKey(config.ItemID))  | 
|                     {  | 
|                         List<StoreData> storeDatas = new List<StoreData>();  | 
|                         storeDatas.Add(storeData);  | 
|                         theOnlyShopDict.Add(config.ItemID, storeDatas);  | 
|                     }  | 
|                     else  | 
|                     {  | 
|                         theOnlyShopDict[config.ItemID].Add(storeData);  | 
|                     }  | 
|                 }  | 
|   | 
|                 string key = StringUtility.Contact(config.ShopType, config.LimitValue);  | 
|                 if (!limitValueShopDict.ContainsKey(key))  | 
|                 {  | 
|                     List<StoreData> storeDatas = new List<StoreData>();  | 
|                     storeDatas.Add(storeData);  | 
|                     limitValueShopDict.Add(key, storeDatas);  | 
|                 }  | 
|                 else  | 
|                 {  | 
|                     limitValueShopDict[key].Add(storeData);  | 
|                 }  | 
|             }  | 
|         }  | 
|   | 
|         foreach (var type in storeTypeDict.Keys)  | 
|         {  | 
|             var configs = storeTypeDict[type];  | 
|             configs.Sort(CompareByShopSort);  | 
|         }  | 
|     }  | 
|   | 
|     private Dictionary<int, List<int>> AnalysisJobReplace(StoreConfig storeConfig)  | 
|     {  | 
|         if (storeConfig == null || string.IsNullOrEmpty(storeConfig.JobItem)) return null;  | 
|   | 
|         Dictionary<int, List<int>> replaceDict = new Dictionary<int, List<int>>();  | 
|         JsonData jsonData = JsonMapper.ToObject(storeConfig.JobItem);  | 
|         if (jsonData.IsArray)  | 
|         {  | 
|             for (int i = 0; i < jsonData.Count; i++)  | 
|             {  | 
|                 List<int> idlist = new List<int>();  | 
|                 replaceDict.Add(i, idlist);  | 
|                 if (jsonData[i].IsArray)  | 
|                 {  | 
|                     for (int j = 0; j < jsonData[i].Count; j++)  | 
|                     {  | 
|                         int itemId = int.Parse(jsonData[i][j].ToString());  | 
|                         idlist.Add(itemId);  | 
|                     }  | 
|                 }  | 
|             }  | 
|         }  | 
|         return replaceDict;  | 
|     }  | 
|   | 
|     public int CompareByShopSort(StoreData start, StoreData end)  | 
|     {  | 
|         int sort1 = start.storeConfig.ShopSort;  | 
|         int sort2 = end.storeConfig.ShopSort;  | 
|   | 
|         return sort1.CompareTo(sort2);  | 
|     }  | 
|   | 
|     public class StoreData  | 
|     {  | 
|         public int shopId;  | 
|         public StoreConfig storeConfig;  | 
|         public Dictionary<int, List<int>> jobReplaceDict;  | 
|     }  | 
|     #endregion  | 
|   | 
|     #region 获取数据  | 
|   | 
|     private Dictionary<int, List<StoreData>> showStoreTypeDict = new Dictionary<int, List<StoreData>>();  | 
|   | 
|     private Dictionary<int, Dictionary<int, List<StoreData>>> showStoreSecondTypeDict = new Dictionary<int, Dictionary<int, List<StoreData>>>();  | 
|   | 
|   | 
|     // 新规则分二级标签,此函数保留,另增加UpdateShowStoreEx函数  | 
|     public void UpdateShowStore()  | 
|     {  | 
|         showStoreTypeDict.Clear();  | 
|         int playeLv = PlayerDatas.Instance.baseData.LV;  | 
|         //int vipLevel = PlayerDatas.Instance.baseData.VIPLv;  | 
|         foreach (var type in storeTypeDict.Keys)  | 
|         {  | 
|             var storeDatas = storeTypeDict[type];  | 
|             List<StoreData> showStoreDatas = new List<StoreData>();  | 
|             if (!showStoreTypeDict.ContainsKey(type))  | 
|             {  | 
|                 for (int i = 0; i < storeDatas.Count; i++)  | 
|                 {  | 
|                     var storeData = storeDatas[i];  | 
|                     bool isReachLv = playeLv >= storeData.storeConfig.LVSee ? true : false;  | 
|   | 
|                     bool isReach = isReachLv;  | 
|                     if (isReach)  | 
|                     {  | 
|                         int remainNum = 0;  | 
|                         bool isSellOut = TryGetIsSellOut(storeData.storeConfig, out remainNum);  | 
|                         if (storeData.storeConfig.IsHideSellOut != 1)  | 
|                         {  | 
|                             showStoreDatas.Add(storeData);  | 
|                         }  | 
|                         else  | 
|                         {  | 
|                             if (storeData.storeConfig.TheOnlyShop == 1)  | 
|                             {  | 
|                                 if (!CheckTheOnlyShopSellOut(storeData.shopId))  | 
|                                 {  | 
|                                     showStoreDatas.Add(storeData);  | 
|                                 }  | 
|                             }  | 
|                             else  | 
|                             {  | 
|                                 if (!isSellOut)  | 
|                                 {  | 
|                                     showStoreDatas.Add(storeData);  | 
|                                 }  | 
|                             }  | 
|                         }  | 
|                     }  | 
|   | 
|                 }  | 
|                 showStoreTypeDict.Add(type, showStoreDatas);  | 
|             }  | 
|         }  | 
|         UpdateShowStoreEx();  | 
|     }  | 
|   | 
|     // 商城分二级标签  | 
|     public void UpdateShowStoreEx()  | 
|     {  | 
|         sortStoreSecondType = true;  | 
|         showStoreSecondTypeDict.Clear();  | 
|         foreach (var type in showStoreTypeDict.Keys)  | 
|         {  | 
|             if (!showStoreSecondTypeDict.ContainsKey(type))  | 
|                 showStoreSecondTypeDict[type] = new Dictionary<int, List<StoreData>>();  | 
|   | 
|             foreach (var storeData in showStoreTypeDict[type])  | 
|             {  | 
|   | 
|                 foreach (var secondType in storeData.storeConfig.SecondType)  | 
|                 {  | 
|                     if (!showStoreSecondTypeDict[type].ContainsKey(secondType))  | 
|                         showStoreSecondTypeDict[type][secondType] = new List<StoreData>();  | 
|   | 
|                     showStoreSecondTypeDict[type][secondType].Add(storeData);  | 
|                 }  | 
|   | 
|             }  | 
|         }  | 
|   | 
|     }  | 
|   | 
|     bool sortStoreSecondType = true;  | 
|   | 
|     public void SortStoreSecondType()  | 
|     {  | 
|         //ArrayList lst = new ArrayList(showStoreSecondTypeDict.Keys);  | 
|         if (!sortStoreSecondType)  | 
|             return;  | 
|   | 
|         foreach (var type in showStoreSecondTypeDict.Keys)  | 
|         {  | 
|             foreach (var secondType in showStoreSecondTypeDict[type].Keys)  | 
|             {  | 
|                 var storeList = showStoreSecondTypeDict[type][secondType];  | 
|                 storeList.Sort(CompareSecondShop);  | 
|             }  | 
|         }  | 
|   | 
|         sortStoreSecondType = false;  | 
|     }  | 
|   | 
|     private bool IsSellOut(StoreData storeData)  | 
|     {  | 
|         int remainNum = 0;  | 
|         if (TryGetIsSellOut(storeData.storeConfig, out remainNum))  | 
|             return true;  | 
|   | 
|         if (storeData.storeConfig.TheOnlyShop == 1 && CheckTheOnlyShopSellOut(storeData.shopId))  | 
|             return true;  | 
|   | 
|         return false;  | 
|     }  | 
|   | 
|     private int CompareSecondShop(StoreData start, StoreData end)  | 
|     {  | 
|         bool isSellOut1 = IsSellOut(start);  | 
|         bool isSellOut2 = IsSellOut(end);  | 
|   | 
|         if (isSellOut1 != isSellOut2)  | 
|             return isSellOut1.CompareTo(isSellOut2);  | 
|         int sort1 = start.storeConfig.ShopSort;  | 
|         int sort2 = end.storeConfig.ShopSort;  | 
|   | 
|         return sort1.CompareTo(sort2);  | 
|     }  | 
|   | 
|     /// <summary>  | 
|     /// 检测唯一商品是否已售罄  | 
|     /// </summary>  | 
|     /// <param name="shopIndex"></param>  | 
|     /// <param name="isTheOnlyShop"></param>  | 
|     /// <returns></returns>  | 
|     public bool CheckTheOnlyShopSellOut(int shopIndex)  | 
|     {  | 
|         StoreConfig storeConfig = StoreConfig.Get(shopIndex);  | 
|         if (storeConfig == null || storeConfig.TheOnlyShop != 1) return false;  | 
|   | 
|         if (theOnlyShopDict.ContainsKey(storeConfig.ItemID))  | 
|         {  | 
|             List<StoreData> datas = theOnlyShopDict[storeConfig.ItemID];  | 
|             for (int i = 0; i < datas.Count; i++)  | 
|             {  | 
|                 var data = datas[i];  | 
|                 int remainNum = 0;  | 
|                 if (TryGetIsSellOut(data.storeConfig, out remainNum))  | 
|                 {  | 
|                     return true;  | 
|                 }  | 
|             }  | 
|         }  | 
|   | 
|         return false;  | 
|     }  | 
|   | 
|     public List<StoreData> TryGetStoreDatas(StoreFunc type)  | 
|     {  | 
|         var results = new List<StoreData>();  | 
|         List<StoreData> datas = null;  | 
|         if (showStoreTypeDict.TryGetValue((int)type, out datas))  | 
|         {  | 
|             results.AddRange(datas);  | 
|             //switch (type)  | 
|             //{  | 
|             //    case StoreFunc.MysteryStore:  | 
|             //        foreach (var item in datas)  | 
|             //        {  | 
|             //            if (mysteryCommondities.Contains(item.storeConfig.ID))  | 
|             //            {  | 
|             //                results.Add(item);  | 
|             //            }  | 
|             //        }  | 
|   | 
|             //        results.Sort((StoreData x, StoreData y) => { return x.storeConfig.MoneyType < y.storeConfig.MoneyType ? -1 : 1; });  | 
|             //        break;  | 
|             //    default:  | 
|             //        results.AddRange(datas);  | 
|             //        break;  | 
|             //}  | 
|         }  | 
|   | 
|         return results;  | 
|     }  | 
|   | 
|     // 获取二级标签商品  | 
|     public List<StoreData> TryGetStoreDatasBySecondType(int type, int secondType)  | 
|     {  | 
|         if (!showStoreSecondTypeDict.ContainsKey(type))  | 
|             return null;  | 
|   | 
|         if (!showStoreSecondTypeDict[type].ContainsKey(secondType))  | 
|             return null;  | 
|   | 
|         SortStoreSecondType();  | 
|         return showStoreSecondTypeDict[type][secondType];  | 
|     }  | 
|   | 
|     // 获得二级标签的第一个标签类型  | 
|     public int GetFirstStoreSecondType(int type, bool jump = true)  | 
|     {  | 
|         if (jump && jumpToItemId != 0)  | 
|         {  | 
|             if (selectSecondType == 0) selectSecondType = 1;  | 
|             return selectSecondType;  | 
|         }  | 
|         if (!showStoreSecondTypeDict.ContainsKey(type))  | 
|             return 1;  | 
|   | 
|         ArrayList sortList = new ArrayList(showStoreSecondTypeDict[type].Keys);  | 
|         sortList.Sort();  | 
|         return (int)sortList[0];  | 
|     }  | 
|   | 
|     // 获得二级标签的第一个标签类型  | 
|     public ArrayList GetStoreSecondTypeList(int type)  | 
|     {  | 
|         if (!showStoreSecondTypeDict.ContainsKey(type))  | 
|             return null;  | 
|   | 
|         ArrayList sortList = new ArrayList(showStoreSecondTypeDict[type].Keys);  | 
|         sortList.Sort();  | 
|         return sortList;  | 
|     }  | 
|   | 
|     public StoreData GetStoreData(int shopId)  | 
|     {  | 
|         StoreConfig storeConfig = StoreConfig.Get(shopId);  | 
|         if (storeConfig == null) return null;  | 
|   | 
|         List<StoreData> storeDatas = null;  | 
|         storeTypeDict.TryGetValue(storeConfig.ShopType, out storeDatas);  | 
|         if (storeDatas != null)  | 
|         {  | 
|             for (int i = 0; i < storeDatas.Count; i++)  | 
|             {  | 
|                 var storeData = storeDatas[i];  | 
|                 if (storeData.shopId == shopId)  | 
|                 {  | 
|                     return storeData;  | 
|                 }  | 
|             }  | 
|         }  | 
|         return null;  | 
|     }  | 
|   | 
|     // 不同职业显示不同物品的情况  | 
|     public int GetReplaceId(int shopId, int itemId)  | 
|     {  | 
|         var storeData = GetStoreData(shopId);  | 
|         if (storeData == null) return 0;  | 
|   | 
|         int job = PlayerDatas.Instance.baseData.Job;  | 
|         var replaceDict = storeData.jobReplaceDict;  | 
|         if (replaceDict != null)  | 
|         {  | 
|             foreach (var index in replaceDict.Keys)  | 
|             {  | 
|                 var idlist = replaceDict[index];  | 
|                 if (idlist.Contains(itemId))  | 
|                 {  | 
|                     int replaceIndex = job - 1;  | 
|                     return idlist[replaceIndex];  | 
|                 }  | 
|             }  | 
|         }  | 
|   | 
|         return itemId;  | 
|     }  | 
|   | 
|     public bool TryGetRedTypeByShopId(int shopId, out int type)  | 
|     {  | 
|         type = 0;  | 
|         foreach (var key in storeRedRuleDict.Keys)  | 
|         {  | 
|             List<int> idlist = storeRedRuleDict[key];  | 
|             if (idlist.Contains(shopId))  | 
|             {  | 
|                 type = key;  | 
|                 return true;  | 
|             }  | 
|         }  | 
|         return false;  | 
|     }  | 
|   | 
|   | 
|   | 
|     public bool TryGetIsSellOut(StoreConfig storeConfig, out int remainCnt)  | 
|     {  | 
|         int canBuyCnt = 0;  | 
|         int addBuyCnt = 0;  | 
|         remainCnt = 0;  | 
|         bool isLimitBuy = TryGetLimitBuy(storeConfig, out canBuyCnt, out addBuyCnt);  | 
|         if (!isLimitBuy) return false;  | 
|   | 
|         remainCnt = canBuyCnt;  | 
|         BuyShopItemLimit shopItemLimit = GetBuyShopLimit((uint)storeConfig.ID);  | 
|         if (shopItemLimit != null)  | 
|         {  | 
|             remainCnt -= shopItemLimit.BuyCnt;  | 
|         }  | 
|   | 
|         if (remainCnt <= 0)  | 
|         {  | 
|             return true;  | 
|         }  | 
|         return false;  | 
|     }  | 
|   | 
|     /// <summary>  | 
|     ///   | 
|     /// </summary>  | 
|     /// <param name="config"></param>  | 
|     /// <param name="canBuyCnt"> 可购买上限</param>  | 
|     /// <param name="addBuyCnt"> 下一级VIP增加的可购买次数</param>  | 
|     /// <returns></returns>  | 
|     public bool TryGetLimitBuy(StoreConfig config, out int canBuyCnt, out int addBuyCnt)  | 
|     {  | 
|         canBuyCnt = 0;  | 
|         addBuyCnt = 0;  | 
|         if (config == null) return false;  | 
|   | 
|         int[] canBuyNums = config.GoumaiNumber;  | 
|         if (canBuyNums == null || canBuyNums.Length < 1) return false;  | 
|   | 
|         int curVipIndex = -1;  | 
|         int nexVipIndex = -1;  | 
|         bool isVipBuy = TryGetVipBuy(config, out curVipIndex, out nexVipIndex);  | 
|         if (isVipBuy)  | 
|         {  | 
|             if (curVipIndex != -1)  | 
|             {  | 
|                 canBuyCnt = canBuyNums[curVipIndex];  | 
|             }  | 
|   | 
|             if (nexVipIndex != -1)  | 
|             {  | 
|                 addBuyCnt = canBuyNums[nexVipIndex] - canBuyCnt;  | 
|             }  | 
|             return true;  | 
|         }  | 
|         else  | 
|         {  | 
|             if (canBuyNums[0] != 0)  | 
|             {  | 
|                 canBuyCnt = canBuyNums[0];  | 
|                 return true;  | 
|             }  | 
|             else  | 
|             {  | 
|                 return false;  | 
|             }  | 
|         }  | 
|     }  | 
|   | 
|     public bool TryGetVipBuy(StoreConfig config, out int curVipIndex, out int nextVipIndex)  | 
|     {  | 
|         curVipIndex = -1;  | 
|         nextVipIndex = -1;  | 
|         bool isVipBuy = false;  | 
|         if (config == null) return false;  | 
|   | 
|         var vipLvs = config.VIPLV;  | 
|         if (vipLvs == null || vipLvs.Length < 1) return false;  | 
|   | 
|         for (int i = 0; i < vipLvs.Length; i++)  | 
|         {  | 
|             var vipLv = vipLvs[i];  | 
|             if (vipLv != 0)  | 
|             {  | 
|                 isVipBuy = true;  | 
|             }  | 
|         }  | 
|   | 
|         if (isVipBuy)  | 
|         {  | 
|             int playerVip = PlayerDatas.Instance.baseData.VIPLv;  | 
|             for (int i = vipLvs.Length - 1; i > -1; i--)  | 
|             {  | 
|                 var vipLv = vipLvs[i];  | 
|                 if (vipLv > playerVip)  | 
|                 {  | 
|                     nextVipIndex = i;  | 
|                 }  | 
|                 else if (vipLv <= playerVip)  | 
|                 {  | 
|                     curVipIndex = i;  | 
|                     break;  | 
|                 }  | 
|             }  | 
|   | 
|         }  | 
|   | 
|         return isVipBuy;  | 
|     }  | 
|   | 
|   | 
|   | 
|     public List<StoreData> TryGetStoreDatasByLimit(int type, int limitValue)  | 
|     {  | 
|         string key = StringUtility.Contact(type, limitValue);  | 
|         List<StoreData> datas = null;  | 
|         limitValueShopDict.TryGetValue(key, out datas);  | 
|         return datas;  | 
|     }  | 
|     #endregion  | 
|   | 
|   | 
|   | 
|     public string GetMysteryStoreRefreshTime()  | 
|     {  | 
|         if (GeneralDefine.mysteryShopRefreshInterval == 0)  | 
|         {  | 
|             return "";  | 
|         }  | 
|         var seconds = GeneralDefine.mysteryShopRefreshInterval -  | 
|              (int)((TimeUtility.ServerNow - TimeUtility.createRoleTime).TotalSeconds) % GeneralDefine.mysteryShopRefreshInterval;  | 
|         return Language.Get("StoreWin200", TimeUtility.SecondsToHMS(seconds));  | 
|     }  | 
|   | 
|     private int GetWillRefreshTime()  | 
|     {  | 
|         int willRefresh = (3 - TimeUtility.OpenDay % 3);  | 
|         if (willRefresh == 3)  | 
|         {  | 
|             if (TimeUtility.ServerNow.Hour < 5)  | 
|             {  | 
|                 willRefresh = 0;  | 
|             }  | 
|         }  | 
|         int remainHour = 5 - TimeUtility.ServerNow.Hour;  | 
|         int remainMinute = 0 - TimeUtility.ServerNow.Minute;  | 
|         int remainSecond = willRefresh * 24 * 60 * 60 + remainHour * 60 * 60 + remainMinute * 60 - TimeUtility.ServerNow.Second;  | 
|         return remainSecond;  | 
|     }  | 
|   | 
|     int refreshTime = 0;  | 
|     private void UpdateSecond()  | 
|     {  | 
|         if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Store)) return;  | 
|         if (isUpdatePlayerLv)  | 
|         {  | 
|             UpdatePlayerLv();  | 
|             isUpdatePlayerLv = false;  | 
|         }  | 
|     }  | 
|   | 
|     private void UpdatePlayerLv()  | 
|     {  | 
|         UpdateShowStore();  | 
|         UpdateFreeShopRedpoint();  | 
|         UpdateCanBuyRedpoint();  | 
|         UpdateMustBuyRedpoint();  | 
|     }  | 
|   | 
|     private void RefreshPlayerData(PlayerDataType type)  | 
|     {  | 
|         if (type == PlayerDataType.VIPLv)  | 
|         {  | 
|             UpdateShowStore();  | 
|         }  | 
|   | 
|         switch (type)  | 
|         {  | 
|             case PlayerDataType.LV:  | 
|                 isUpdatePlayerLv = true;  | 
|                 break;  | 
|             case PlayerDataType.VIPLv:  | 
|             case PlayerDataType.Gold:  | 
|             case PlayerDataType.GoldPaper:  | 
|                 UpdateFreeShopRedpoint();  | 
|                 UpdateCanBuyRedpoint();  | 
|                 UpdateDailyRedpoinit();  | 
|                 break;  | 
|             case PlayerDataType.UnionLiven:  | 
|                 UpdateDailyRedpoinit();  | 
|                 break;  | 
|             case PlayerDataType.FBHelpPoint:  | 
|                 UpdateFreeShopRedpoint();  | 
|                 UpdateCanBuyRedpoint();  | 
|                 break;  | 
|         }  | 
|     }  | 
|   | 
|     private void RefreshFamilyLv()  | 
|     {  | 
|         int familyLv = PlayerDatas.Instance.fairyData.fairy.FamilyLV;  | 
|         if (familyLv > GetSaveFairyLV())  | 
|         {  | 
|             ControllerRedPoint();  | 
|         }  | 
|         UpdateDailyRedpoinit();  | 
|     }  | 
|   | 
|     private void RefreshServerHour()  | 
|     {  | 
|         ControllerRedPoint();  | 
|         if (PlayerPrefs.HasKey(MUSTBUYSAVE_KEY))  | 
|         {  | 
|             int[] records = LocalSave.GetIntArray(MUSTBUYSAVE_KEY);  | 
|             if (TimeUtility.ServerNow.Hour >= 5  | 
|                 && ((TimeUtility.ServerNow.Day == records[0] && records[1] < 5)  | 
|                 || TimeUtility.ServerNow.Day != records[0]))  | 
|             {  | 
|                 saveTimes[0] = TimeUtility.ServerNow.Day;  | 
|                 saveTimes[1] = TimeUtility.ServerNow.Hour;  | 
|                 IsMustBuyDay = true;  | 
|                 LocalSave.SetIntArray(MUSTBUYSAVE_KEY, saveTimes);  | 
|                 UpdateMustBuyRedpoint();  | 
|             }  | 
|         }  | 
|         if (!PlayerDatas.Instance.fairyData.HasFairy)  | 
|         {  | 
|             PlayerPrefs.DeleteKey(UNIONSTORESAVE_KEY);  | 
|         }  | 
|   | 
|         UpdateDailyRedpoinit();  | 
|     }  | 
|   | 
|     public event Action RefreshBuyShopLimitEvent;  | 
|   | 
|     public StoreFunc storeFuncType = StoreFunc.DayStore;  | 
|     public int jumpStoreFuncType { get; set; }  | 
|     private Dictionary<uint, BuyShopItemLimit> shopItemlimitDict = new Dictionary<uint, BuyShopItemLimit>();  | 
|   | 
|     /// <summary>  | 
|     /// 得到物品购买次数  | 
|     /// </summary>  | 
|     /// <param name="buylimit"></param>  | 
|     public void RefreshBuyShopLimitModel(HA802_tagMCShopItemDayBuyCntInfo buylimit)  | 
|     {  | 
|         Debug.Log("RefreshBuyShopLimitModel" + buylimit.Count);  | 
|         if (buylimit.Count > 0)  | 
|         {  | 
|             int i = 0;  | 
|             for (i = 0; i < buylimit.Count; i++)  | 
|             {  | 
|                 if (!shopItemlimitDict.ContainsKey(buylimit.DayBuyCntList[i].ItemIndex))  | 
|                 {  | 
|                     BuyShopItemLimit shopItemLimit = new BuyShopItemLimit();  | 
|                     shopItemLimit.ItemIndex = buylimit.DayBuyCntList[i].ItemIndex;  | 
|                     shopItemLimit.BuyCnt = (int)buylimit.DayBuyCntList[i].BuyCnt;  | 
|                     shopItemLimit.isReset = buylimit.DayBuyCntList[i].IsReset;  | 
|                     shopItemlimitDict.Add(shopItemLimit.ItemIndex, shopItemLimit);  | 
|                 }  | 
|                 else  | 
|                 {  | 
|                     shopItemlimitDict[buylimit.DayBuyCntList[i].ItemIndex].BuyCnt = (int)buylimit.DayBuyCntList[i].BuyCnt;  | 
|                     shopItemlimitDict[buylimit.DayBuyCntList[i].ItemIndex].isReset = buylimit.DayBuyCntList[i].IsReset;  | 
|                 }  | 
|             }  | 
|   | 
|         }  | 
|   | 
|         sortStoreSecondType = true;  | 
|         UpdateShowStore();  | 
|         UpdateFreeShopRedpoint();  | 
|         UpdateCanBuyRedpoint();  | 
|         UpdateMustBuyRedpoint();  | 
|         UpdateDailyRedpoinit();  | 
|         if (RefreshBuyShopLimitEvent != null)  | 
|             RefreshBuyShopLimitEvent();  | 
|     }  | 
|   | 
|     public BuyShopItemLimit GetBuyShopLimit(uint itemIndex)  | 
|     {  | 
|         if (shopItemlimitDict.ContainsKey(itemIndex))  | 
|         {  | 
|             return shopItemlimitDict[itemIndex];  | 
|         }  | 
|         return null;  | 
|     }  | 
|   | 
|   | 
|   | 
|     //和GetShopItemlistEx 一样 获取商店物品列表,只是返回类型不同  | 
|     List<ShopItemInfo> shopItemlist = new List<ShopItemInfo>();  | 
|     public List<ShopItemInfo> GetShopItemlistByIndex(StoreConfig storeConfig)  | 
|     {  | 
|         if (storeConfig == null) return null;  | 
|   | 
|         shopItemlist.Clear();  | 
|         if (storeConfig.ItemID != 0)  | 
|         {  | 
|             int replaceId = GetReplaceId(storeConfig.ID, storeConfig.ItemID);  | 
|             ShopItemInfo shopItem = new ShopItemInfo(replaceId, storeConfig.ItemCnt);  | 
|             shopItemlist.Add(shopItem);  | 
|         }  | 
|         JsonData extraItem = JsonMapper.ToObject(storeConfig.ItemListEx);  | 
|         if (extraItem.IsArray)  | 
|         {  | 
|             for (int i = 0; i < extraItem.Count; i++)  | 
|             {  | 
|                 if (extraItem[i].IsArray)  | 
|                 {  | 
|                     if (extraItem[i].Count > 0)  | 
|                     {  | 
|                         int itemId = int.Parse(extraItem[i][0].ToString());  | 
|                         int itemCount = int.Parse(extraItem[i][1].ToString());  | 
|                         if (itemId != 0)  | 
|                         {  | 
|                             int extraReplaceId = GetReplaceId(storeConfig.ID, itemId);  | 
|                             ShopItemInfo shop = new ShopItemInfo(extraReplaceId, itemCount);  | 
|                             shopItemlist.Add(shop);  | 
|                         }  | 
|                     }  | 
|                 }  | 
|             }  | 
|         }  | 
|         return shopItemlist;  | 
|     }  | 
|   | 
|     //和GetShopItemlistByIndex 一样 获取商店物品列表,只是返回类型不同  | 
|     public List<int[]> GetShopItemlistEx(StoreConfig storeConfig)  | 
|     {  | 
|         if (storeConfig == null) return null;  | 
|   | 
|         List<int[]> shopItemlist = new List<int[]>();  | 
|         if (storeConfig.ItemID != 0)  | 
|         {  | 
|             int replaceId = GetReplaceId(storeConfig.ID, storeConfig.ItemID);  | 
|             shopItemlist.Add(new int[] { replaceId, storeConfig.ItemCnt, 0 });  | 
|         }  | 
|         var extraItem = JsonMapper.ToObject<int[][]>(storeConfig.ItemListEx);  | 
|         for (int i = 0; i < extraItem.Length; i++)  | 
|         {  | 
|             shopItemlist.Add(extraItem[i]);  | 
|         }  | 
|         return shopItemlist;  | 
|     }  | 
|   | 
|     public bool TryGetShopItemInfo(StoreFunc _type, int _id, out List<ShopItemInfo> _shopItems)  | 
|     {  | 
|         _shopItems = null;  | 
|         var _list = TryGetStoreDatas(_type);  | 
|         var _index = _list.FindIndex((x) =>  | 
|         {  | 
|             return x.shopId == _id;  | 
|         });  | 
|         if (_index == -1)  | 
|         {  | 
|             return false;  | 
|         }  | 
|         _shopItems = GetShopItemlistByIndex(_list[_index].storeConfig);  | 
|         return _shopItems != null;  | 
|     }  | 
|   | 
|   | 
|     #region 点击商店物品逻辑  | 
|     public void OnClickShopCell(StoreConfig shopInfo)  | 
|     {  | 
|         int itemId = GetReplaceId(shopInfo.ID, shopInfo.ItemID);  | 
|         ItemTipUtility.Show(itemId);  | 
|     }  | 
|   | 
|     public int BuyCnt { get; private set; }  | 
|     public void SetBuyCnt(int buyCnt)  | 
|     {  | 
|         BuyCnt = buyCnt;  | 
|     }  | 
|   | 
|     #endregion  | 
|   | 
|     private long _price;  | 
|     public void SendBuyShopItem(StoreConfig model, int count)  | 
|     {  | 
|   | 
|         _price = model.MoneyNumber * count;  | 
|   | 
|         if (MoneyIsEnough(model.MoneyType, _price))  | 
|         {  | 
|             var vipLv = PlayerDatas.Instance.baseData.VIPLv;  | 
|             var itemMinLv = model.VIPLV[0];  | 
|             if (vipLv < itemMinLv)  | 
|             {  | 
|                 SysNotifyMgr.Instance.ShowTip("VIPNotEnough", itemMinLv);  | 
|             }  | 
|             else  | 
|             {  | 
|                 CA310_tagCMBuyItem buyShop = new CA310_tagCMBuyItem();  | 
|                 buyShop.BuyItemIndex = (ushort)model.ID;  | 
|                 buyShop.BuyCount = (uint)count;  | 
|                 GameNetSystem.Instance.SendInfo(buyShop);  | 
|             }  | 
|         }  | 
|         else  | 
|         {  | 
|             switch (model.MoneyType)  | 
|             {  | 
|                 case 1:  | 
|                     if (VersionConfig.Get().isBanShu)  | 
|                     {  | 
|                         SysNotifyMgr.Instance.ShowTip("GoldErr");  | 
|                         return;  | 
|                     }  | 
|                     // WindowCenter.Instance.Open<RechargeTipWin>();  | 
|                     break;  | 
|                 case 25:  | 
|                     SysNotifyMgr.Instance.ShowTip("LackXBMoney", model.MoneyType);  | 
|                     break;  | 
|                 default:  | 
|                     SysNotifyMgr.Instance.ShowTip("LackMoney", model.MoneyType);  | 
|                     break;  | 
|             }  | 
|         }  | 
|   | 
|     }  | 
|   | 
|     //仙玉购买物品的二次确认框,一级货币只有仙玉 默认为仙玉即可  | 
|     Dictionary<int, bool> buyItemCheckDict = new Dictionary<int, bool>();   //记录勾选信息  | 
|     //eventType 二次确认框类型,对应枚举 BuyStoreItemCheckType  | 
|     public void SendBuyShopItemWithPopCheck(StoreConfig model, int count, int eventType = 0)  | 
|     {  | 
|         if (model.MoneyNumber == 0)  | 
|         {  | 
|             //免费的  | 
|             SendBuyShopItem(model, count);  | 
|             return;  | 
|         }  | 
|   | 
|         if (buyItemCheckDict.ContainsKey(eventType) && buyItemCheckDict[eventType])  | 
|         {  | 
|             SendBuyShopItem(model, count);  | 
|             return;  | 
|         }  | 
|   | 
|         ConfirmCancel.ToggleConfirmCancel(Language.Get("Mail101"), Language.Get("OSTimeLimitGiftConfirm", model.MoneyNumber),  | 
|         Language.Get("ConfirmCancel102"), (Action<bool, bool>)((bool isOk, bool isToggle) =>  | 
|         {  | 
|             if (isOk)  | 
|             {  | 
|                 SendBuyShopItem(model, count);  | 
|                 buyItemCheckDict[eventType] = isToggle;  | 
|             }  | 
|               | 
|         }));  | 
|     }  | 
|   | 
|     //花仙玉购买的二次确认框(本次登录)  | 
|     //eventType 二次确认框类型,对应枚举 BuyStoreItemCheckType  | 
|     public void UseMoneyCheck(int money, int moneyType, Action func, int eventType = 0, string tip = "CostMoney", string fullTip = "")  | 
|     {  | 
|         if (money == 0)  | 
|         {  | 
|             //免费的  | 
|             func?.Invoke();  | 
|             return;  | 
|         }  | 
|   | 
|         if (buyItemCheckDict.ContainsKey(eventType) && buyItemCheckDict[eventType])  | 
|         {  | 
|             func?.Invoke();  | 
|             return;  | 
|         }  | 
|   | 
|         ConfirmCancel.ToggleConfirmCancel(Language.Get("Mail101"), fullTip == "" ? Language.Get(tip, money, moneyType) : fullTip,  | 
|             Language.Get("ConfirmCancel102"), (bool isOk, bool isToggle) =>  | 
|             {  | 
|                 if (isOk)  | 
|                 {  | 
|                     func?.Invoke();  | 
|                     buyItemCheckDict[eventType] = isToggle;  | 
|                 }  | 
|   | 
|             });  | 
|     }  | 
|   | 
|   | 
|   | 
|     public event Action<int> RefreshBuyResultEvent;  | 
|   | 
|     public void GetBuyResult(HA811_tagMCShoppingResult result)  | 
|     {  | 
|   | 
|         //Debug.Log("GetBuyResult");  | 
|         StoreConfig tagStore = StoreConfig.Get((int)result.ItemIndex);  | 
|   | 
|         if (tagStore != null)  | 
|         {  | 
|             ItemConfig chinModel = ItemConfig.Get(GetReplaceId(tagStore.ID, tagStore.ItemID));  | 
|             if (tagStore.RemindSuccess == 0)  | 
|             {  | 
|                 return;  | 
|             }  | 
|   | 
|             if (RefreshBuyResultEvent != null)  | 
|             {  | 
|                 RefreshBuyResultEvent(chinModel.ID);  | 
|             }  | 
|         }  | 
|     }  | 
|   | 
|   | 
|     public bool MoneyIsEnough(int moneyType, long money)  | 
|     {  | 
|         if (UIHelper.GetMoneyCnt(moneyType) < money)  | 
|         {  | 
|             return false;  | 
|         }  | 
|         else  | 
|         {  | 
|             return true;  | 
|         }  | 
|     }  | 
|   | 
|     public int funcOrder { get; private set; }  | 
|     public int jumpToItemId { get; set; }  | 
|   | 
|     /// <summary>  | 
|     /// 会先清之前的跳转,调用者要注意 ClearJump  | 
|     /// </summary>  | 
|     /// <param name="itemId"></param>  | 
|     public void SetJumpToModel(int itemId)  | 
|     {  | 
|         ClearJump();  | 
|         jumpToItemId = itemId;  | 
|     }  | 
|   | 
|     public void ClearJump()  | 
|     {  | 
|         funcOrder = -1;  | 
|         jumpToItemId = 0;  | 
|     }  | 
|   | 
|     public void SetWinOrder(int order)  | 
|     {  | 
|         funcOrder = order;  | 
|     }  | 
|   | 
|     public void OpenStoreWin(bool forceSync = false, int functionOrder = 0, bool useJump = false)  | 
|     {  | 
|         if (useJump && funcOrder != -1)  | 
|         {  | 
|             // WindowCenter.Instance.Open<StoreWin>(forceSync, funcOrder);  | 
|         }  | 
|         else  | 
|         {   | 
|             ClearJump();  | 
|             // WindowCenter.Instance.Open<StoreWin>(forceSync, functionOrder);  | 
|         }  | 
|     }  | 
|   | 
|     public event Action StoreFuncOpenAct;  | 
|   | 
|     private void FuncStateChange(int funcId)  | 
|     {  | 
|         switch ((FuncOpenEnum)funcId)  | 
|         {  | 
|             case FuncOpenEnum.Store:  | 
|                 if (StoreFuncOpenAct != null)  | 
|                 {  | 
|                     StoreFuncOpenAct();  | 
|                 }  | 
|                 UpdateFreeShopRedpoint();  | 
|                 UpdateCanBuyRedpoint();  | 
|                 UpdateMustBuyRedpoint();  | 
|                 UpdateDailyRedpoinit();  | 
|                 break;  | 
|             // case FuncOpenEnum.BlastFurnace:  | 
|             //     ControllerRedPoint();  | 
|             //     break;  | 
|         }  | 
|     }  | 
|   | 
|     public bool IsNewDay(string recordKey)  | 
|     {  | 
|         if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Store)) return false;  | 
|   | 
|         if (PlayerPrefs.HasKey(recordKey))  | 
|         {  | 
|             int day = LocalSave.GetInt(recordKey);  | 
|             if (day != TimeUtility.ServerNow.Day)  | 
|             {  | 
|                 LocalSave.SetInt(recordKey, TimeUtility.ServerNow.Day);  | 
|                 return true;  | 
|             }  | 
|             else  | 
|             {  | 
|                 return false;  | 
|             }  | 
|         }  | 
|         else  | 
|         {  | 
|             LocalSave.SetInt(recordKey, TimeUtility.ServerNow.Day);  | 
|             return true;  | 
|         }  | 
|     }  | 
|   | 
|     public bool IsRequireDailyRedRemind(int shopId)  | 
|     {  | 
|         var config = StoreConfig.Get(shopId);  | 
|         if (config == null)  | 
|         {  | 
|             return false;  | 
|         }  | 
|         var key = StringUtility.Contact("Store_", config.ShopType, "_", "Daily", shopId);  | 
|         var array = LocalSave.GetIntArray(key);  | 
|         if (array != null && array.Length == 2)  | 
|         {  | 
|             if (array[0] < TimeUtility.Day - 1)  | 
|             {  | 
|                 return true;  | 
|             }  | 
|             else if (array[0] == TimeUtility.Day - 1)  | 
|             {  | 
|                 return array[1] < 5 || TimeUtility.Hour >= 5;  | 
|             }  | 
|             else if (array[0] == TimeUtility.Day)  | 
|             {  | 
|                 return array[1] < 5 && TimeUtility.Hour >= 5;  | 
|             }  | 
|         }  | 
|         return true;  | 
|     }  | 
|   | 
|     public void SetDailyRedRedmind(int shopId)  | 
|     {  | 
|         var config = StoreConfig.Get(shopId);  | 
|         if (config == null)  | 
|         {  | 
|             return;  | 
|         }  | 
|         var key = StringUtility.Contact("Store_", config.ShopType, "_", "Daily", shopId);  | 
|         LocalSave.SetIntArray(key, new int[2] { TimeUtility.Day, TimeUtility.Hour });  | 
|         UpdateDailyRedpoinit();  | 
|     }  | 
|     #region 商城红点  | 
|   | 
|     #region 仙盟红点逻辑处理  | 
|   | 
|     private bool CheckIsBuyNewItem(int fairyLv)  | 
|     {  | 
|         if (fairyLv > GetSaveFairyLV())  | 
|         {  | 
|             var toolStoreDatas = TryGetStoreDatasByLimit((int)StoreFunc.ToolStore, fairyLv);  | 
|             var mountStoreDatas = TryGetStoreDatasByLimit((int)StoreFunc.MountStoneStore, fairyLv);  | 
|             var skillBookStoreData = TryGetStoreDatasByLimit((int)StoreFunc.MountSkillBookStore, fairyLv);  | 
|             if ((toolStoreDatas != null && toolStoreDatas.Count > 0)  | 
|                 || (mountStoreDatas != null && mountStoreDatas.Count > 0)  | 
|                 || (skillBookStoreData != null && skillBookStoreData.Count > 0))  | 
|             {  | 
|                 return true;  | 
|             }  | 
|         }  | 
|         return false;  | 
|     }  | 
|   | 
|     private bool CheckIsNewMonth()  | 
|     {  | 
|         GetSaveDateTime();  | 
|         if (datelist.Count > 0)  | 
|         {  | 
|             if (TimeUtility.ServerNow.Month == datelist[0])  | 
|             {  | 
|                 if (TimeUtility.ServerNow.Day >= 1  | 
|                     && TimeUtility.ServerNow.Hour >= 5  | 
|                     && datelist[1] <= 1 && datelist[2] < 5)  | 
|                 {  | 
|                     return true;  | 
|                 }  | 
|             }  | 
|             else  | 
|             {  | 
|                 if (TimeUtility.ServerNow.Day >= 1  | 
|                     && TimeUtility.ServerNow.Hour >= 5)  | 
|                 {  | 
|                     return true;  | 
|                 }  | 
|             }  | 
|         }  | 
|         return false;  | 
|     }  | 
|   | 
|     List<int> datelist = new List<int>();  | 
|     public List<int> GetSaveDateTime()  | 
|     {  | 
|         datelist.Clear();  | 
|         int[] unionArray = LocalSave.GetIntArray(UNIONSTORESAVE_KEY);  | 
|         if (unionArray != null && unionArray.Length >= 4)  | 
|         {  | 
|             datelist.Add(unionArray[1]);  | 
|             datelist.Add(unionArray[2]);  | 
|             datelist.Add(unionArray[3]);  | 
|         }  | 
|         return datelist;  | 
|     }  | 
|   | 
|     public int GetSaveFairyLV()  | 
|     {  | 
|         int[] unionArray = LocalSave.GetIntArray(UNIONSTORESAVE_KEY);  | 
|         int fairyLv = 0;  | 
|         if (unionArray != null)  | 
|         {  | 
|             return unionArray[0];  | 
|         }  | 
|         return fairyLv;  | 
|     }  | 
|   | 
|   | 
|     //1仙盟等级 2 月份 3 号 4 几点  | 
|     public void SetStoreLocalSave(LocalSaveStoreType saveStoreType, params int[] infos)  | 
|     {  | 
|         string key = StringUtility.Contact(PlayerDatas.Instance.baseData.PlayerID, saveStoreType);  | 
|         LocalSave.SetIntArray(key, infos);  | 
|     }  | 
|   | 
|     public void ControllerRedPoint(bool isLook = false)  | 
|     {  | 
|         fairyStoreRemindRedpoint.state = RedPointState.None;  | 
|         // if (!FairyModel.Instance.fairyStoreOpen  | 
|         //     || !FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.BlastFurnace))  | 
|         // {  | 
|         //     return;  | 
|         // }  | 
|   | 
|         int familyLv = PlayerDatas.Instance.fairyData.fairy.FamilyLV;  | 
|         if (!isLook)  | 
|         {  | 
|             if (CheckIsBuyNewItem(familyLv))  | 
|             {  | 
|                 fairyStoreRemindRedpoint.state = RedPointState.Simple;  | 
|                 return;  | 
|             }  | 
|   | 
|             if (CheckIsNewMonth())  | 
|             {  | 
|                 fairyStoreRemindRedpoint.state = RedPointState.Simple;  | 
|                 return;  | 
|             }  | 
|         }  | 
|   | 
|         SetStoreLocalSave(LocalSaveStoreType.UnionStore, familyLv, TimeUtility.ServerNow.Month,  | 
|                 TimeUtility.ServerNow.Day, TimeUtility.ServerNow.Hour);  | 
|     }  | 
|   | 
|     #endregion  | 
|   | 
|     public const int StoreFunc_RedKey = 22;  | 
|     public const int StoreFunc1_RedKey = 2201;  | 
|     public const int StoreFunc2_RedKey = 2202;  | 
|     public const int StoreFunc3_RedKey = 2203;  | 
|     public const int StoreFunc4_RedKey = 2204;  | 
|     public const int StoreFunc5_RedKey = 2205;  | 
|     public const int StoreFunc8_RedKey = 2208;  | 
|     public const int FairyStoreRemind_RedKey = 107010601;  | 
|     public Redpoint storeFuncPoint = new Redpoint(StoreFunc_RedKey);  | 
|     public Redpoint storeFunc1Point = new Redpoint(StoreFunc_RedKey, StoreFunc1_RedKey);  | 
|     public Redpoint storeFunc2Point = new Redpoint(StoreFunc_RedKey, StoreFunc2_RedKey);  | 
|     public Redpoint storeFunc3Point = new Redpoint(StoreFunc_RedKey, StoreFunc3_RedKey);  | 
|     public Redpoint storeFunc4Point = new Redpoint(StoreFunc_RedKey, StoreFunc4_RedKey);  | 
|     public Redpoint storeFunc5Point = new Redpoint(StoreFunc_RedKey, StoreFunc5_RedKey);  | 
|     public Redpoint storeFunc8Point = new Redpoint(MainRedDot.FAIRYStore_REDPOINT_KEY3, StoreFunc8_RedKey);  | 
|     public Redpoint fairyStoreRemindRedpoint = new Redpoint(MainRedDot.FAIRYStore_REDPOINT_KEY3, FairyStoreRemind_RedKey);  | 
|     public Dictionary<int, Redpoint> shopRedDict = new Dictionary<int, Redpoint>();  | 
|     public void SetShopRedpoint()  | 
|     {  | 
|         shopRedDict.Clear();  | 
|         List<StoreConfig> storelist = StoreConfig.GetValues();  | 
|         for (int i = 0; i < storelist.Count; i++)  | 
|         {  | 
|             StoreConfig storeConfig = storelist[i];  | 
|             int redKey = 0;  | 
|             Redpoint redpoint = null;  | 
|             switch (storeConfig.ShopType)  | 
|             {  | 
|                 //case 1:  | 
|                 //    redKey = StoreFunc1_RedKey * 10000 + storeConfig.ID;  | 
|                 //    redpoint = new Redpoint(StoreFunc1_RedKey, redKey);  | 
|                 //    shopRedDict.Add(storeConfig.ID, redpoint);  | 
|                 //    break;  | 
|                 //case 2:  | 
|                 //    redKey = StoreFunc2_RedKey * 10000 + storeConfig.ID;  | 
|                 //    redpoint = new Redpoint(StoreFunc2_RedKey, redKey);  | 
|                 //    shopRedDict.Add(storeConfig.ID, redpoint);  | 
|                 //    break;  | 
|                 //case 3:  | 
|                 //    redKey = StoreFunc3_RedKey * 10000 + storeConfig.ID;  | 
|                 //    redpoint = new Redpoint(StoreFunc3_RedKey, redKey);  | 
|                 //    shopRedDict.Add(storeConfig.ID, redpoint);  | 
|                 //    break;  | 
|                 //case 4:  | 
|                 //    redKey = StoreFunc4_RedKey * 10000 + storeConfig.ID;  | 
|                 //    redpoint = new Redpoint(StoreFunc4_RedKey, redKey);  | 
|                 //    shopRedDict.Add(storeConfig.ID, redpoint);  | 
|                 //    break;  | 
|                 //case 5:  | 
|                 //    redKey = StoreFunc5_RedKey * 10000 + storeConfig.ID;  | 
|                 //    redpoint = new Redpoint(StoreFunc5_RedKey, redKey);  | 
|                 //    shopRedDict.Add(storeConfig.ID, redpoint);  | 
|                 //    break;  | 
|                 case 8:  | 
|                     redKey = StoreFunc8_RedKey * 10000 + storeConfig.ID;  | 
|                     redpoint = new Redpoint(StoreFunc8_RedKey, redKey);  | 
|                     shopRedDict.Add(storeConfig.ID, redpoint);  | 
|                     break;  | 
|             }  | 
|         }  | 
|     }  | 
|   | 
|     public void UpdateFreeShopRedpoint()  | 
|     {  | 
|         if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Store)) return;  | 
|   | 
|         foreach (var key in showStoreTypeDict.Keys)  | 
|         {  | 
|             var storeDatas = showStoreTypeDict[key];  | 
|             for (int i = 0; i < storeDatas.Count; i++)  | 
|             {  | 
|                 var storeConfig = storeDatas[i].storeConfig;  | 
|                 int type = 0;  | 
|                 TryGetRedTypeByShopId(storeConfig.ID, out type);  | 
|                 if (type == 1)  | 
|                 {  | 
|                     int remainNum = 0;  | 
|                     if (shopRedDict.ContainsKey(storeConfig.ID))  | 
|                     {  | 
|                         if (!TryGetIsSellOut(storeConfig, out remainNum))  | 
|                         {  | 
|                             shopRedDict[storeConfig.ID].state = RedPointState.Simple;  | 
|                         }  | 
|                         else  | 
|                         {  | 
|                             shopRedDict[storeConfig.ID].state = RedPointState.None;  | 
|                         }  | 
|                     }  | 
|                 }  | 
|             }  | 
|   | 
|         }  | 
|     }  | 
|   | 
|     public void UpdateCanBuyRedpoint()  | 
|     {  | 
|         if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Store)) return;  | 
|   | 
|         foreach (var key in showStoreTypeDict.Keys)  | 
|         {  | 
|             var storeDatas = showStoreTypeDict[key];  | 
|             for (int i = 0; i < storeDatas.Count; i++)  | 
|             {  | 
|                 var storeConfig = storeDatas[i].storeConfig;  | 
|                 int type = 0;  | 
|                 TryGetRedTypeByShopId(storeConfig.ID, out type);  | 
|                 if (type == 4)  | 
|                 {  | 
|                     int remainNum = 0;  | 
|                     if (shopRedDict.ContainsKey(storeConfig.ID))  | 
|                     {  | 
|                         if (!TryGetIsSellOut(storeConfig, out remainNum))  | 
|                         {  | 
|                             if (UIHelper.GetMoneyCnt(storeConfig.MoneyType) >= storeConfig.MoneyNumber)  | 
|                             {  | 
|                                 shopRedDict[storeConfig.ID].state = RedPointState.Simple;  | 
|                             }  | 
|                             else  | 
|                             {  | 
|                                 shopRedDict[storeConfig.ID].state = RedPointState.None;  | 
|                             }  | 
|                         }  | 
|                         else  | 
|                         {  | 
|                             shopRedDict[storeConfig.ID].state = RedPointState.None;  | 
|                         }  | 
|   | 
|                     }  | 
|                 }  | 
|             }  | 
|   | 
|         }  | 
|     }  | 
|   | 
|     public void UpdateMustBuyRedpoint()  | 
|     {  | 
|         if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Store)) return;  | 
|   | 
|         foreach (var key in showStoreTypeDict.Keys)  | 
|         {  | 
|             var storeDatas = showStoreTypeDict[key];  | 
|             for (int i = 0; i < storeDatas.Count; i++)  | 
|             {  | 
|                 var storeConfig = storeDatas[i].storeConfig;  | 
|                 int type = 0;  | 
|                 TryGetRedTypeByShopId(storeConfig.ID, out type);  | 
|                 if (type == 2)  | 
|                 {  | 
|                     if (shopRedDict.ContainsKey(storeConfig.ID))  | 
|                     {  | 
|                         if (CheckIsMustBuy(storeConfig))  | 
|                         {  | 
|                             shopRedDict[storeConfig.ID].state = RedPointState.Simple;  | 
|                         }  | 
|                         else  | 
|                         {  | 
|                             shopRedDict[storeConfig.ID].state = RedPointState.None;  | 
|                         }  | 
|                     }  | 
|                 }  | 
|             }  | 
|   | 
|         }  | 
|     }  | 
|   | 
|     public void UpdateDailyRedpoinit()  | 
|     {  | 
|         if (storeRedRuleDict.ContainsKey(6))  | 
|         {  | 
|             var shopIds = storeRedRuleDict[6];  | 
|             var count = 0;  | 
|             foreach (var shopId in shopIds)  | 
|             {  | 
|                 var redable = false;  | 
|                 var config = StoreConfig.Get(shopId);  | 
|                 if (config == null)  | 
|                 {  | 
|                     Debug.LogError($"StoreConfig {shopId} is null");  | 
|                     continue;  | 
|                 }  | 
|                 switch (config.ShopType)  | 
|                 {  | 
|                     case 8:  | 
|                         if (TryGetIsSellOut(config, out count))  | 
|                         {  | 
|                             break;  | 
|                         }  | 
|                         if (PlayerDatas.Instance.fairyData.fairy == null)  | 
|                         {  | 
|                             break;  | 
|                         }  | 
|                         if (config.VIPLV.Length > 0  | 
|                             && PlayerDatas.Instance.baseData.VIPLv < config.VIPLV[0])  | 
|                         {  | 
|                             break;  | 
|                         }  | 
|                         if (PlayerDatas.Instance.fairyData.fairy.FamilyLV < config.LimitValue)  | 
|                         {  | 
|                             break;  | 
|                         }  | 
|                         if (!MoneyIsEnough(config.MoneyType, config.MoneyNumber))  | 
|                         {  | 
|                             break;  | 
|                         }  | 
|                         redable = IsRequireDailyRedRemind(shopId);  | 
|                         break;  | 
|                 }  | 
|   | 
|                 if (shopRedDict.ContainsKey(shopId))  | 
|                 {  | 
|                     shopRedDict[shopId].state = redable ? RedPointState.Simple : RedPointState.None;  | 
|                 }  | 
|             }  | 
|         }  | 
|     }  | 
|   | 
|       | 
|   | 
|   | 
|     public void ClearMustBuyRedpoint(StoreConfig storeConfig)  | 
|     {  | 
|         if (!shopRedDict.ContainsKey(storeConfig.ID))  | 
|             return;  | 
|         int type = 0;  | 
|         TryGetRedTypeByShopId(storeConfig.ID, out type);  | 
|         if (type == 2)  | 
|         {  | 
|             shopRedDict[storeConfig.ID].state = RedPointState.None;  | 
|             IsMustBuyDay = false;  | 
|         }  | 
|         else if (type == 1)  | 
|         {  | 
|             shopRedDict[storeConfig.ID].state = RedPointState.None;  | 
|         }  | 
|     }  | 
|   | 
|     public bool IsMustBuyDay { get; private set; }  | 
|     int[] saveTimes = new int[2];  | 
|     public void SetIsMustBuyDay()  | 
|     {  | 
|         if (IsMustBuyDay) return;  | 
|   | 
|         saveTimes[0] = TimeUtility.ServerNow.Day;  | 
|         saveTimes[1] = TimeUtility.ServerNow.Hour;  | 
|         if (PlayerPrefs.HasKey(MUSTBUYSAVE_KEY))  | 
|         {  | 
|             int[] records = LocalSave.GetIntArray(MUSTBUYSAVE_KEY);  | 
|             if (TimeUtility.ServerNow.Hour >= 5  | 
|                 && ((TimeUtility.ServerNow.Day == records[0] && records[1] < 5)  | 
|                 || TimeUtility.ServerNow.Day != records[0]))  | 
|             {  | 
|                 IsMustBuyDay = true;  | 
|                 LocalSave.SetIntArray(MUSTBUYSAVE_KEY, saveTimes);  | 
|             }  | 
|             else  | 
|             {  | 
|                 IsMustBuyDay = false;  | 
|             }  | 
|         }  | 
|         else  | 
|         {  | 
|             IsMustBuyDay = true;  | 
|             LocalSave.SetIntArray(MUSTBUYSAVE_KEY, saveTimes);  | 
|         }  | 
|     }  | 
|   | 
|     public bool CheckIsMustBuy(StoreConfig config)  | 
|     {  | 
|         int remainNum = 0;  | 
|         if (!TryGetIsSellOut(config, out remainNum) && IsMustBuyDay)  | 
|         {  | 
|             return true;  | 
|         }  | 
|         return false;  | 
|     }  | 
|   | 
|       | 
|     public void ClearPetAndMountRedpoint(StoreConfig storeConfig)  | 
|     {  | 
|         ItemConfig itemConfig = ItemConfig.Get(storeConfig.ItemID);  | 
|         switch (itemConfig.Type)  | 
|         {  | 
|             case 26:  | 
|             case 41:  | 
|                 string key = StringUtility.Contact(PlayerDatas.Instance.baseData.PlayerID, "ShopId", storeConfig.ID);  | 
|                 if (shopRedDict.ContainsKey(storeConfig.ID) && shopRedDict[storeConfig.ID].state == RedPointState.Simple)  | 
|                 {  | 
|                     shopRedDict[storeConfig.ID].state = RedPointState.None;  | 
|                     LocalSave.SetBool(key, false);  | 
|                 }  | 
|                 break;  | 
|         }  | 
|     }  | 
|   | 
|     public void ClearAllPetAndMountRedpoint(StoreFunc storeFunc)  | 
|     {  | 
|         if (storeFuncType == StoreFunc.BindStore && storeFunc != StoreFunc.BindStore)  | 
|         {  | 
|             foreach (var key in shopRedDict.Keys)  | 
|             {  | 
|                 StoreConfig storeConfig = StoreConfig.Get(key);  | 
|                 ItemConfig itemConfig = ItemConfig.Get(storeConfig.ItemID);  | 
|                 switch (itemConfig.Type)  | 
|                 {  | 
|                     case 26:  | 
|                     case 41:  | 
|                         if (shopRedDict.ContainsKey(key) && shopRedDict[key].state != RedPointState.None)  | 
|                         {  | 
|                             string record = StringUtility.Contact(PlayerDatas.Instance.baseData.PlayerID, "ShopId", key);  | 
|                             shopRedDict[key].state = RedPointState.None;  | 
|                             LocalSave.SetBool(record, false);  | 
|                         }  | 
|                         break;  | 
|                 }  | 
|   | 
|             }  | 
|         }  | 
|   | 
|     }  | 
|   | 
|     public void CloseRedPoint(StoreConfig storeConfig)  | 
|     {  | 
|         ClearMustBuyRedpoint(storeConfig);  | 
|         ClearPetAndMountRedpoint(storeConfig);  | 
|     }  | 
|   | 
|     public void CloseAllRedpoint(StoreFunc storeFunc)  | 
|     {  | 
|         ClearAllPetAndMountRedpoint(storeFunc);  | 
|     }  | 
|     #endregion  | 
|   | 
|       | 
|   | 
|   | 
| }  | 
|   | 
| public enum StoreFunc  | 
| {  | 
|     DayStore = 1, //1:每天限购  | 
|     CommonStore = 2, //2:幻境阁商店  | 
|     GrowStrongerStore = 3, //3:成长变强  | 
|     BindStore = 4,  //4:绑玉商城  | 
|     IntegralStore = 5,  //5:积分商城  | 
|     BagStore = 6,  //6:随身商店  | 
|     RuneStore = 7,  //7:符印商店  | 
|     ToolStore = 8, // 道具商店  | 
|     MountStoneStore = 9, //坐骑魂石商店  | 
|     MountSkillBookStore = 10,//坐骑技能书商店  | 
|     XBEquipStore = 11, //寻宝装备商店  | 
|     XBRuneStore = 12, //寻宝符印商店  | 
|     XBToolStore = 13, //寻宝道具商店  | 
|     OSGift = 14,//开服礼包  | 
|     OSTimeLimitGift = 15,//限时特惠  | 
|     CrossOneVsOneHonor = 17,//荣誉商店  | 
|     MysteryStore = 18, //1:神秘商店  | 
|     default1,  | 
|     default2, //时间类活动 - 如boss凭证的商店 20  | 
|     default3,  | 
|     QCTrainActStore = 306, //骑宠养成活动商店  | 
|     CelestialPalaceStore = 308, //仙宫商店(天道阁)  | 
| }  | 
|   | 
| public enum LocalSaveStoreType  | 
| {  | 
|     UnionStore, //仙盟商店  | 
|   | 
| }  | 
|   |