hch
6 天以前 ee3196b5a04c15d025d1a9eab825d5d14987758d
Main/System/Store/StoreModel.cs
@@ -6,14 +6,9 @@
using LitJson;
using System.Collections;
public class BuyShopItemLimit
{
    public uint ItemIndex;
    public int BuyCnt;        // 今日已购买次数
    public int isReset;         //是否属于每月重置  0 不重置 1重置
}
public struct ShopItemInfo
public class ShopItemInfo
{
    public int itemId;
    public int count;
@@ -27,149 +22,87 @@
public class StoreModel : GameSystemManager<StoreModel>
{
    public Dictionary<int, List<StoreData>> storeTypeDict { get; private set; } //所有显示商品
    public Dictionary<int, int> shopRefreshCntDict = new Dictionary<int, int>();    //刷新次数
    private Dictionary<int, int> shopItemlimitDict = new Dictionary<int, int>();    //已购买次数
    public event Action RefreshBuyShopLimitEvent;
    public event Action RefreshShopEvent;
    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 StoreFunc selectStoreFuncType = StoreFunc.Normal;
    public int fairyStoreJumpShopId = 0;
    public int buyShopID;
    int m_SelectClassifyId = 0;
    public int selectSecondType
    {
        get { return m_SelectClassifyId; }
        set
        {
            if (m_SelectClassifyId != value)
            {
                m_SelectClassifyId = value;
                if (selectClassifyRefresh != null)
                {
                    selectClassifyRefresh();
                }
            }
        }
    }
    //配置
    public int heroSoulRefreshMoneyType;
    public int heroSoulRefreshMoney;
    public int heroSoulRefreshFreeCount;
    public event Action selectClassifyRefresh;
    private bool isUpdatePlayerLv;
    //排行榜活动的商店
    public int rankActStore_MoneyType;
    public int rankActStore_StoreType;
    public OperationType rankActStore_ActType;
    Dictionary<int, List<int>> freeShopDict = new Dictionary<int, List<int>>();
    public Dictionary<int, int> shopMoneyTypeDict = new Dictionary<int, int>();
    public override void Init()
    {
        RedpointCenter.Instance.AddParent(MainRedDot.MainGuildRedpoint, MainRedDot.Store_REDPOINT);
        FuncOpen.Instance.OnFuncStateChangeEvent += FuncStateChange;
        TimeMgr.Instance.OnDayEvent += RefreshDay;
        GuildManager.Instance.EnterOrQuitGuildEvent += EnterOrQuitGuildEvent;
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeRelogin;
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize;
        ParseFuncConfig();
        ParseStoreConfig();
        SetShopRedpoint();
    }
    public void OnBeforePlayerDataInitialize()
    public override void Release()
    {
        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;
        TimeMgr.Instance.OnDayEvent -= RefreshDay;
        GuildManager.Instance.EnterOrQuitGuildEvent -= EnterOrQuitGuildEvent;
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeRelogin;
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize;
    }
    void OnBeforePlayerDataInitialize()
    {
        shopItemlimitDict.Clear();
        storeFuncType = StoreFunc.DayStore;
        storeTypeDict.Remove((int)StoreFunc.Hero);  //由服务器通知
        selectStoreFuncType = StoreFunc.Normal;
    }
    public void OnAfterPlayerDataInitialize()
    void OnBeforePlayerDataInitializeRelogin()
    {
        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);
                }
            }
        }
        var config = FuncConfigConfig.Get("StoreHeroSoul");
        var tmpArr = ConfigParse.GetMultipleStr<int>(config.Numerical2);
        heroSoulRefreshMoneyType = tmpArr[0];
        heroSoulRefreshMoney = tmpArr[1];
        heroSoulRefreshFreeCount = int.Parse(config.Numerical3);
    }
    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()
    {
        freeShopDict.Clear();
        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)
            //UnlockType 2 由服务端通知
            if (config.ShopType != 0 && config.UnlockType != 2)
            {
                //构建商品数据
                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>();
@@ -181,31 +114,21 @@
                    storeTypeDict[config.ShopType].Add(storeData);
                }
                if (config.TheOnlyShop == 1)
                //构建免费商品数据
                if (config.MoneyNum == 0)
                {
                    if (!theOnlyShopDict.ContainsKey(config.ItemID))
                    if (!freeShopDict.ContainsKey(config.ShopType))
                    {
                        List<StoreData> storeDatas = new List<StoreData>();
                        storeDatas.Add(storeData);
                        theOnlyShopDict.Add(config.ItemID, storeDatas);
                        freeShopDict.Add(config.ShopType, new List<int>());
                    }
                    else
                    {
                        theOnlyShopDict[config.ItemID].Add(storeData);
                    }
                    freeShopDict[config.ShopType].Add(config.ID);
                }
            }
                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);
                }
            //构建商品价格类型
            if (!shopMoneyTypeDict.ContainsKey(config.ShopType))
            {
                shopMoneyTypeDict[config.ShopType] = config.MoneyType;
            }
        }
@@ -216,30 +139,7 @@
        }
    }
    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)
    {
@@ -253,114 +153,11 @@
    {
        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)
    {
@@ -368,122 +165,24 @@
        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))
        if (storeTypeDict.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 datas;
        }
        return results;
        return datas;
    }
    // 获取二级标签商品
    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);
@@ -505,61 +204,21 @@
        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;
        int canBuyCnt = storeConfig.LimitCnt;
        remainCnt = 0;
        bool isLimitBuy = TryGetLimitBuy(storeConfig, out canBuyCnt, out addBuyCnt);
        if (!isLimitBuy) return false;
        //不限购
        if (canBuyCnt == 0) return false;
        remainCnt = canBuyCnt;
        BuyShopItemLimit shopItemLimit = GetBuyShopLimit((uint)storeConfig.ID);
        if (shopItemLimit != null)
        {
            remainCnt -= shopItemLimit.BuyCnt;
        }
        var buyCnt = GetShopLimitBuyCount(storeConfig.ID);
        remainCnt -= buyCnt;
        if (remainCnt <= 0)
        {
@@ -568,304 +227,105 @@
        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()
    private void RefreshDay()
    {
        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)
    void EnterOrQuitGuildEvent(bool isEnter)
    {
        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;
        }
        UpdateFreeShopRedpoint();
    }
    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)
    public void RefreshBuyShopLimitModel(HA802_tagSCShopItemBuyCntInfo buylimit)
    {
        Debug.Log("RefreshBuyShopLimitModel" + buylimit.Count);
        if (buylimit.Count > 0)
        int i = 0;
        for (i = 0; i < buylimit.Count; i++)
        {
            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;
                }
            }
            shopItemlimitDict[(int)buylimit.BuyCntList[i].ShopID] = (int)buylimit.BuyCntList[i].BuyCnt;
        }
        sortStoreSecondType = true;
        UpdateShowStore();
        UpdateFreeShopRedpoint();
        UpdateCanBuyRedpoint();
        UpdateMustBuyRedpoint();
        UpdateDailyRedpoinit();
        if (RefreshBuyShopLimitEvent != null)
            RefreshBuyShopLimitEvent();
    }
    public BuyShopItemLimit GetBuyShopLimit(uint itemIndex)
    // 限购商品已购买次数
    public int GetShopLimitBuyCount(int shopID)
    {
        if (shopItemlimitDict.ContainsKey(itemIndex))
        if (shopItemlimitDict.ContainsKey(shopID))
        {
            return shopItemlimitDict[itemIndex];
            return shopItemlimitDict[shopID];
        }
        return null;
        return 0;
    }
    public void UpdateRefreshItemInfo(HA803_tagSCShopRefreshItemInfo netPack)
    {
        storeTypeDict.Remove(netPack.ShopType);
        shopRefreshCntDict[netPack.ShopType] = netPack.RefreshCnt;
        List<int> resortList = new List<int>();
        for (int i = 0; i < netPack.ShopIDList.Length; i++)
        {
            var config = StoreConfig.Get((int)netPack.ShopIDList[i]);
            //UnlockType 2 由服务端通知
            StoreData storeData = new StoreData();
            storeData.shopId = config.ID;
            storeData.storeConfig = 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 (storeTypeDict.ContainsKey(netPack.ShopType))
        {
            var configs = storeTypeDict[netPack.ShopType];
            configs.Sort(CompareByShopSort);
        }
        RefreshShopEvent?.Invoke();
    }
    //和GetShopItemlistEx 一样 获取商店物品列表,只是返回类型不同
    List<ShopItemInfo> shopItemlist = new List<ShopItemInfo>();
    public List<ShopItemInfo> GetShopItemlistByIndex(StoreConfig storeConfig)
    {
        if (storeConfig == null) return null;
        List<ShopItemInfo> shopItemlist = new List<ShopItemInfo>();
        shopItemlist.Clear();
        if (storeConfig.ItemID != 0)
        {
            int replaceId = GetReplaceId(storeConfig.ID, storeConfig.ItemID);
            ShopItemInfo shopItem = new ShopItemInfo(replaceId, storeConfig.ItemCnt);
            ShopItemInfo shopItem = new ShopItemInfo(storeConfig.ID, storeConfig.ItemCnt);
            shopItemlist.Add(shopItem);
        }
        JsonData extraItem = JsonMapper.ToObject(storeConfig.ItemListEx);
        if (extraItem.IsArray)
        var extraItem = storeConfig.ItemListEx;
        if (extraItem != null)
        {
            for (int i = 0; i < extraItem.Count; i++)
            for (int i = 0; i < extraItem.Length; 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);
                        }
                    }
                }
                ShopItemInfo shop = new ShopItemInfo(extraItem[i][0], extraItem[i][1]);
                shopItemlist.Add(shop);
            }
        }
        return shopItemlist;
@@ -879,10 +339,9 @@
        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 });
            shopItemlist.Add(new int[] { storeConfig.ID, storeConfig.ItemCnt});
        }
        var extraItem = JsonMapper.ToObject<int[][]>(storeConfig.ItemListEx);
        var extraItem = storeConfig.ItemListEx;
        for (int i = 0; i < extraItem.Length; i++)
        {
            shopItemlist.Add(extraItem[i]);
@@ -890,79 +349,21 @@
        return shopItemlist;
    }
    public bool TryGetShopItemInfo(StoreFunc _type, int _id, out List<ShopItemInfo> _shopItems)
    public bool TryGetShopItemInfo(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);
        _shopItems = GetShopItemlistByIndex(StoreConfig.Get(_id));
        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))
        if (UIHelper.CheckMoneyCount(model.MoneyType, model.MoneyNum * count, 2))
        {
            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;
            }
            CA310_tagCSBuyItem buyShop = new CA310_tagCSBuyItem();
            buyShop.ShopID = (ushort)model.ID;
            buyShop.BuyCount = (uint)count;
            GameNetSystem.Instance.SendInfo(buyShop);
        }
    }
@@ -972,7 +373,7 @@
    //eventType 二次确认框类型,对应枚举 BuyStoreItemCheckType
    public void SendBuyShopItemWithPopCheck(StoreConfig model, int count, int eventType = 0)
    {
        if (model.MoneyNumber == 0)
        if (model.MoneyNum == 0)
        {
            //免费的
            SendBuyShopItem(model, count);
@@ -985,8 +386,8 @@
            return;
        }
        ConfirmCancel.ToggleConfirmCancel(Language.Get("Mail101"), Language.Get("OSTimeLimitGiftConfirm", model.MoneyNumber),
        Language.Get("ConfirmCancel102"), (Action<bool, bool>)((bool isOk, bool isToggle) =>
        ConfirmCancel.ToggleConfirmCancel(Language.Get("Mail101"), Language.Get("CostMoney", model.MoneyNum, model.MoneyType),
        Language.Get("ConfirmCancel102"), (bool isOk, bool isToggle) =>
        {
            if (isOk)
            {
@@ -994,7 +395,7 @@
                buyItemCheckDict[eventType] = isToggle;
            }
            
        }));
        });
    }
    //花仙玉购买的二次确认框(本次登录)
@@ -1028,640 +429,126 @@
    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;
            }
        }
    }
    Redpoint storeRedpoint = new Redpoint(MainRedDot.RightFuncRedpoint, MainRedDot.Store_REDPOINT);
    Redpoint normalRedpoint = new Redpoint(MainRedDot.Store_REDPOINT, MainRedDot.Store_REDPOINT * 10 + 1);
    Redpoint guildRedpoint = new Redpoint(MainRedDot.Store_REDPOINT, MainRedDot.Store_REDPOINT * 10 + 2);
    public void UpdateFreeShopRedpoint()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Store)) return;
        foreach (var key in showStoreTypeDict.Keys)
        normalRedpoint.state = RedPointState.None;
        guildRedpoint.state = RedPointState.None;
        if (freeShopDict.Count == 0) return;
        if (freeShopDict.ContainsKey((int)StoreFunc.Normal))
        {
            var storeDatas = showStoreTypeDict[key];
            for (int i = 0; i < storeDatas.Count; i++)
            var shopList = freeShopDict[(int)StoreFunc.Normal];
            for (int i = 0; i < shopList.Count; i++)
            {
                var storeConfig = storeDatas[i].storeConfig;
                int type = 0;
                TryGetRedTypeByShopId(storeConfig.ID, out type);
                if (type == 1)
                var shopID = shopList[i];
                var config = StoreConfig.Get(shopID);
                if (shopItemlimitDict.ContainsKey(shopID))
                {
                    int remainNum = 0;
                    if (shopRedDict.ContainsKey(storeConfig.ID))
                    if (shopItemlimitDict[shopID] < config.LimitCnt)
                    {
                        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);
                        normalRedpoint.state = RedPointState.Simple;
                        break;
                    }
                }
                if (shopRedDict.ContainsKey(shopId))
                else
                {
                    shopRedDict[shopId].state = redable ? RedPointState.Simple : RedPointState.None;
                    normalRedpoint.state = RedPointState.Simple;
                    break;
                }
            }
        }
    }
    public void ClearMustBuyRedpoint(StoreConfig storeConfig)
    {
        if (!shopRedDict.ContainsKey(storeConfig.ID))
            return;
        int type = 0;
        TryGetRedTypeByShopId(storeConfig.ID, out type);
        if (type == 2)
        if (PlayerDatas.Instance.fairyData.HasFairy && freeShopDict.ContainsKey((int)StoreFunc.Guild))
        {
            shopRedDict[storeConfig.ID].state = RedPointState.None;
            IsMustBuyDay = false;
        }
        else if (type == 1)
        {
            shopRedDict[storeConfig.ID].state = RedPointState.None;
        }
    }
            var shopList = freeShopDict[(int)StoreFunc.Guild];
    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]))
            for (int i = 0; i < shopList.Count; i++)
            {
                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)
                var shopID = shopList[i];
                var config = StoreConfig.Get(shopID);
                if (shopItemlimitDict.ContainsKey(shopID))
                {
                    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);
                        }
                    if (shopItemlimitDict[shopID] < config.LimitCnt)
                    {
                        guildRedpoint.state = RedPointState.Simple;
                        break;
                    }
                }
                else
                {
                    guildRedpoint.state = RedPointState.Simple;
                    break;
                }
            }
        }
    }
    public void CloseRedPoint(StoreConfig storeConfig)
    {
        ClearMustBuyRedpoint(storeConfig);
        ClearPetAndMountRedpoint(storeConfig);
    }
    public void CloseAllRedpoint(StoreFunc storeFunc)
    {
        ClearAllPetAndMountRedpoint(storeFunc);
    }
    #endregion
    public void RefreshStore(int shopType)
    {
        var pack = new CA232_tagCSRefreshShop();
        pack.ShopType = (ushort)shopType;
        GameNetSystem.Instance.SendInfo(pack);
    }
    //获取商品状态  0可购买 1已售罄 2免费 3未解锁
    public int GetShopIDState(int shopID)
    {
        var config = StoreConfig.Get(shopID);
        if (config.UnlockType == 1)
        {
            if (!PlayerDatas.Instance.fairyData.HasFairy ||
            PlayerDatas.Instance.fairyData.fairy.FamilyLV < config.UnlockValue)
            {
                return 3;
            }
        }
        if (config.LimitCnt != 0 && GetShopLimitBuyCount(shopID) >= config.LimitCnt)
        {
            return 1;
        }
        if (config.MoneyNum == 0)
        {
            return 2;
        }
        return 0;
    }
}
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, //仙宫商店(天道阁)
    Normal = 1, //1:坊市
    Guild = 2, //2:公会
    Hero = 3, //3:将魂
}
public enum LocalSaveStoreType
{
    UnionStore, //仙盟商店
}