fix:1、修复bug 2、删除不用的代码和资源,sdk等

This commit is contained in:
2026-05-07 14:56:44 +08:00
parent 99145facbd
commit 28d582c373
378 changed files with 79341 additions and 86716 deletions
+280 -280
View File
@@ -1,281 +1,281 @@
using System;
using System.Collections;
using System.Collections.Generic;
using DataEyeAnalytics;
using Newtonsoft.Json;
using UnityEngine;
namespace BallKingdomCrush
{
public class BIManager : MonoBehaviour
{
private static BIManager _instance;
private static readonly object _initLock = new object();
// 状态标志
private bool _initialized = false; // 仅在初始化成功后为 true
private bool _initializing = false; // 防止并发多次尝试初始化
private string ntpServer = "time.windows.com";
private string defaultChannel = "gp";
private int maxInitRetries = 6;
private float retryIntervalSeconds = 0.5f;
public static BIManager Instance
{
get
{
if (_instance == null)
{
var go = new GameObject("BIManager");
DontDestroyOnLoad(go);
_instance = go.AddComponent<BIManager>();
}
return _instance;
}
}
private void Awake()
{
// 单例保护:如果场景里已有实例,销毁重复的
if (_instance == null)
{
_instance = this;
DontDestroyOnLoad(gameObject);
}
else if (_instance != this)
{
Destroy(gameObject);
return;
}
}
private void Start()
{
// Start 调用 InitBI 是安全的:InitBI 本身是幂等且线程安全的
InitBI();
}
/// <summary>
/// 对外统一初始化入口(幂等、线程安全)
/// </summary>
public void InitBI()
{
// 快速检查
if (_initialized) return;
lock (_initLock)
{
if (_initialized || _initializing)
{
// 已经初始化或正在初始化,直接返回
return;
}
_initializing = true;
}
// 使用协程执行初始化(必要时可以做重试)
StartCoroutine(DoInitCoroutine());
}
private IEnumerator DoInitCoroutine()
{
try
{
int attempt = 0;
Exception lastException = null;
while (attempt < maxInitRetries)
{
attempt++;
try
{
// 这里不主动调用 DataEyeAnalyticsAPI.Init(...) 假设你使用的是场景里的 DataEyeAnalytics 预制体,
// SDK 会在预制体 Awake/Start 里初始化。如果你的流程是手动 Init,请在这里调用 Init(appId)。
// 1) 校准时间(默认实例)
DataEyeAnalyticsAPI.CalibrateTimeWithNtp(ntpServer);
// 2) 设置超参数
var superProperties = new Dictionary<string, object>
{
{ "channel", defaultChannel }
};
DataEyeAnalyticsAPI.SetSuperProperties(superProperties);
// 3) 开启自动采集
DataEyeAnalyticsAPI.EnableAutoTrack(AUTO_TRACK_EVENTS.ALL);
// 如果上面没有抛异常,认为初始化成功
_initialized = true;
Debug.Log($"[BIManager] InitBI succeeded on attempt {attempt}");
yield break;
}
catch (ArgumentNullException ane)
{
// 典型:DataEye 内部 instance 还没创建(appId 为 null -> retry
lastException = ane;
Debug.LogWarning(
$"[BIManager] DataEye not ready (attempt {attempt}), will retry. msg={ane.Message}");
}
catch (Exception ex)
{
// 其他异常,记录并决定是否重试
lastException = ex;
Debug.LogWarning($"[BIManager] InitBI attempt {attempt} threw: {ex.Message}");
}
// 等待后重试
yield return new WaitForSeconds(retryIntervalSeconds);
}
// 重试用尽仍失败 —— 打日志(不再抛异常以免影响游戏流程)
Debug.LogError("[BIManager] InitBI failed after retries. Last exception: " +
(lastException?.ToString() ?? "null"));
}
finally
{
lock (_initLock)
{
_initializing = false;
}
}
}
// ================= 通用埋点 =================
public void TrackEvent(string eventName, Dictionary<string, object> properties = null)
{
if (properties == null)
properties = new Dictionary<string, object>();
DataEyeAnalyticsAPI.Track(eventName, properties);
DataEyeAnalyticsAPI.Flush();
Debug.Log($"[BI] 事件上报: {eventName}, 属性={JsonConvert.SerializeObject(properties)}");
}
// ================= 预制事件封装 =================
/// <summary>
/// 上报广告事件
/// </summary>
/// <param name="eventName"></param>
/// <param name="adType">NativeRewardedVideoBannerInterstitialSplash</param>
/// <param name="placementId">聚合广告位id</param>
/// <param name="networkFirmId">广告网络ID</param>
public void TrackAdEvent(string eventName, string adType, string placementId = null,
string networkFirmId = null, double revenue = 0, string scene = null, string currency = "USD")
{
var props = new Dictionary<string, object>
{
{ "ad_type", adType }
};
if (!string.IsNullOrEmpty(placementId))
props["PlacementId"] = placementId;
if (!string.IsNullOrEmpty(networkFirmId))
props["NetworkFirmId"] = networkFirmId;
if (revenue > 0)
{
props["Revenue"] = revenue;
props["Ecpm"] = revenue * 1000;
}
if (!string.IsNullOrEmpty(scene))
props["scene"] = scene;
if (!string.IsNullOrEmpty(currency))
props["Currency"] = currency;
TrackEvent(eventName, props);
}
/// <summary>
/// 上报内购事件
/// </summary>
/// <param name="revenue">收入</param>
/// <param name="currency">币种</param>
/// <param name="payType">支付方式 0=商店支付,1=三方支付</param>
/// <param name="itemId">sku</param>
/// <param name="status">order:下单 paid:付费成功 paid_err:扣款失败</param>
/// <param name="itemName">商品名称</param>
/// <param name="msg">如果遇到异常或相关情况,将err_msg进行上报</param>
public void TrackPurchase(double revenue, string currency, string payType, string itemId,
string status, string itemName = null, string msg = null)
{
var props = new Dictionary<string, object>
{
{ "Revenue", revenue },
{ "Currency", currency },
{ "type", payType },
{ "item_id", itemId },
{ "purchase_status", status }
};
if (!string.IsNullOrEmpty(itemName))
props["item_name"] = itemName;
if (!string.IsNullOrEmpty(msg))
props["msg"] = msg;
TrackEvent(BIEvent.PURCHASE, props);
}
/// <summary>
/// 上报页面浏览
/// </summary>
public void TrackPageView(string pageName)
{
var props = new Dictionary<string, object>
{
{ "page_name", pageName } // 例如 "loading"、"game"
};
TrackEvent(BIEvent.PAGE_VIEW, props);
}
/// <summary>
/// AB 分组埋点
/// </summary>
public void TrackABConfig(int responseTime)
{
var props = new Dictionary<string, object>
{
{ "response_time", responseTime }
};
TrackEvent(BIEvent.AB_CONFIG, props);
}
}
}
public static class BIEvent
{
// 自动采集(SDK 开启自动采集即可,不需要手动埋点)
public const string APP_INSTALL = "app_install";
public const string APP_START = "app_start";
public const string APP_END = "app_end";
public const string APP_VIEW = "app_view";
public const string APP_CRASH = "app_crash";
// 内部预制事件
public const string AD_REQUEST = "ad_request"; // 广告请求
public const string AD_INVENTORY = "ad_inventory"; // 广告填充的时候
public const string AD_IMP = "ad_imp"; // 广告展示
public const string AD_CLICK = "ad_click"; // 广告点击
public const string PURCHASE = "purchase"; // 内购
// 页面相关
public const string PAGE_VIEW = "page_view_customize";
// 其他业务事件(AB 测试等)
public const string AB_CONFIG = "config"; // AB
using System;
using System.Collections;
using System.Collections.Generic;
using DataEyeAnalytics;
using Newtonsoft.Json;
using UnityEngine;
namespace BallKingdomCrush
{
public class BIManager : MonoBehaviour
{
private static BIManager _instance;
private static readonly object _initLock = new object();
// 状态标志
private bool _initialized = false; // 仅在初始化成功后为 true
private bool _initializing = false; // 防止并发多次尝试初始化
private string ntpServer = "time.windows.com";
private string defaultChannel = "gp";
private int maxInitRetries = 6;
private float retryIntervalSeconds = 0.5f;
public static BIManager Instance
{
get
{
if (_instance == null)
{
var go = new GameObject("BIManager");
DontDestroyOnLoad(go);
_instance = go.AddComponent<BIManager>();
}
return _instance;
}
}
private void Awake()
{
// 单例保护:如果场景里已有实例,销毁重复的
if (_instance == null)
{
_instance = this;
DontDestroyOnLoad(gameObject);
}
else if (_instance != this)
{
Destroy(gameObject);
return;
}
}
private void Start()
{
// Start 调用 InitBI 是安全的:InitBI 本身是幂等且线程安全的
InitBI();
}
/// <summary>
/// 对外统一初始化入口(幂等、线程安全)
/// </summary>
public void InitBI()
{
// 快速检查
if (_initialized) return;
lock (_initLock)
{
if (_initialized || _initializing)
{
// 已经初始化或正在初始化,直接返回
return;
}
_initializing = true;
}
// 使用协程执行初始化(必要时可以做重试)
StartCoroutine(DoInitCoroutine());
}
private IEnumerator DoInitCoroutine()
{
try
{
int attempt = 0;
Exception lastException = null;
while (attempt < maxInitRetries)
{
attempt++;
try
{
// 这里不主动调用 DataEyeAnalyticsAPI.Init(...) 假设你使用的是场景里的 DataEyeAnalytics 预制体,
// SDK 会在预制体 Awake/Start 里初始化。如果你的流程是手动 Init,请在这里调用 Init(appId)。
// 1) 校准时间(默认实例)
DataEyeAnalyticsAPI.CalibrateTimeWithNtp(ntpServer);
// 2) 设置超参数
var superProperties = new Dictionary<string, object>
{
{ "channel", defaultChannel }
};
DataEyeAnalyticsAPI.SetSuperProperties(superProperties);
// 3) 开启自动采集
DataEyeAnalyticsAPI.EnableAutoTrack(AUTO_TRACK_EVENTS.ALL);
// 如果上面没有抛异常,认为初始化成功
_initialized = true;
Debug.Log($"[BIManager] InitBI succeeded on attempt {attempt}");
yield break;
}
catch (ArgumentNullException ane)
{
// 典型:DataEye 内部 instance 还没创建(appId 为 null -> retry
lastException = ane;
Debug.LogWarning(
$"[BIManager] DataEye not ready (attempt {attempt}), will retry. msg={ane.Message}");
}
catch (Exception ex)
{
// 其他异常,记录并决定是否重试
lastException = ex;
Debug.LogWarning($"[BIManager] InitBI attempt {attempt} threw: {ex.Message}");
}
// 等待后重试
yield return new WaitForSeconds(retryIntervalSeconds);
}
// 重试用尽仍失败 —— 打日志(不再抛异常以免影响游戏流程)
Debug.LogError("[BIManager] InitBI failed after retries. Last exception: " +
(lastException?.ToString() ?? "null"));
}
finally
{
lock (_initLock)
{
_initializing = false;
}
}
}
// ================= 通用埋点 =================
public void TrackEvent(string eventName, Dictionary<string, object> properties = null)
{
// if (properties == null)
// properties = new Dictionary<string, object>();
//
// DataEyeAnalyticsAPI.Track(eventName, properties);
// DataEyeAnalyticsAPI.Flush();
//
// Debug.Log($"[BI] 事件上报: {eventName}, 属性={JsonConvert.SerializeObject(properties)}");
}
// ================= 预制事件封装 =================
/// <summary>
/// 上报广告事件
/// </summary>
/// <param name="eventName"></param>
/// <param name="adType">NativeRewardedVideoBannerInterstitialSplash</param>
/// <param name="placementId">聚合广告位id</param>
/// <param name="networkFirmId">广告网络ID</param>
public void TrackAdEvent(string eventName, string adType, string placementId = null,
string networkFirmId = null, double revenue = 0, string scene = null, string currency = "USD")
{
var props = new Dictionary<string, object>
{
{ "ad_type", adType }
};
if (!string.IsNullOrEmpty(placementId))
props["PlacementId"] = placementId;
if (!string.IsNullOrEmpty(networkFirmId))
props["NetworkFirmId"] = networkFirmId;
if (revenue > 0)
{
props["Revenue"] = revenue;
props["Ecpm"] = revenue * 1000;
}
if (!string.IsNullOrEmpty(scene))
props["scene"] = scene;
if (!string.IsNullOrEmpty(currency))
props["Currency"] = currency;
TrackEvent(eventName, props);
}
/// <summary>
/// 上报内购事件
/// </summary>
/// <param name="revenue">收入</param>
/// <param name="currency">币种</param>
/// <param name="payType">支付方式 0=商店支付,1=三方支付</param>
/// <param name="itemId">sku</param>
/// <param name="status">order:下单 paid:付费成功 paid_err:扣款失败</param>
/// <param name="itemName">商品名称</param>
/// <param name="msg">如果遇到异常或相关情况,将err_msg进行上报</param>
public void TrackPurchase(double revenue, string currency, string payType, string itemId,
string status, string itemName = null, string msg = null)
{
var props = new Dictionary<string, object>
{
{ "Revenue", revenue },
{ "Currency", currency },
{ "type", payType },
{ "item_id", itemId },
{ "purchase_status", status }
};
if (!string.IsNullOrEmpty(itemName))
props["item_name"] = itemName;
if (!string.IsNullOrEmpty(msg))
props["msg"] = msg;
TrackEvent(BIEvent.PURCHASE, props);
}
/// <summary>
/// 上报页面浏览
/// </summary>
public void TrackPageView(string pageName)
{
var props = new Dictionary<string, object>
{
{ "page_name", pageName } // 例如 "loading"、"game"
};
TrackEvent(BIEvent.PAGE_VIEW, props);
}
/// <summary>
/// AB 分组埋点
/// </summary>
public void TrackABConfig(int responseTime)
{
var props = new Dictionary<string, object>
{
{ "response_time", responseTime }
};
TrackEvent(BIEvent.AB_CONFIG, props);
}
}
}
public static class BIEvent
{
// 自动采集(SDK 开启自动采集即可,不需要手动埋点)
public const string APP_INSTALL = "app_install";
public const string APP_START = "app_start";
public const string APP_END = "app_end";
public const string APP_VIEW = "app_view";
public const string APP_CRASH = "app_crash";
// 内部预制事件
public const string AD_REQUEST = "ad_request"; // 广告请求
public const string AD_INVENTORY = "ad_inventory"; // 广告填充的时候
public const string AD_IMP = "ad_imp"; // 广告展示
public const string AD_CLICK = "ad_click"; // 广告点击
public const string PURCHASE = "purchase"; // 内购
// 页面相关
public const string PAGE_VIEW = "page_view_customize";
// 其他业务事件(AB 测试等)
public const string AB_CONFIG = "config"; // AB
}
+99 -99
View File
@@ -1,100 +1,100 @@
using Firebase;
using Firebase.Analytics;
using Firebase.Extensions;
using UnityEngine;
namespace BallKingdomCrush
{
public class FireBaseManger: MonoBehaviour
{
public static bool IsReady { get; private set; } = false;
void Start()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
{
if (task.Result == DependencyStatus.Available)
{
Debug.Log("Firebase 初始化成功");
// 启用 Analytics
FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);
IsReady = true;
}
else
{
Debug.LogError("Firebase 依赖错误: " + task.Result);
}
});
}
/// <summary>
/// Max 广告的收益上传Firebase
/// </summary>
/// <param name="adUnitId"></param>
/// <param name="adInfo"></param>
public static void OnAdRevenuePaid(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
if (!IsReady)
{
Debug.LogWarning("Firebase 未初始化完成,丢弃本次广告打点");
return;
}
double revenue = adInfo.Revenue; // 收入,单位是美元 (USD)
string networkName = adInfo.NetworkName;
string adFormat = adInfo.AdFormat;
string adUnitIdentifier = adInfo.AdUnitIdentifier;
Debug.Log($"AppLovin 广告收入: {revenue} USD, 网络: {networkName}, 广告位: {adUnitId}");
// 上报到 Firebase
var impressionParameters = new[] {
new Firebase.Analytics.Parameter("ad_platform", "AppLovin"),
new Firebase.Analytics.Parameter("ad_source", networkName),
new Firebase.Analytics.Parameter("ad_unit_name", adUnitIdentifier),
new Firebase.Analytics.Parameter("ad_format", adFormat),
new Firebase.Analytics.Parameter("value", revenue),
new Firebase.Analytics.Parameter("currency", "USD"), // All AppLovin revenue is sent in USD
};
Firebase.Analytics.FirebaseAnalytics.LogEvent("ad_impression", impressionParameters);
Debug.Log("已上报 ad_impression 事件到 Firebase");
}
/// <summary>
/// 支付的收益上传Firebase
/// </summary>
public static void OnPayRevenueEvent(double value)
{
if (!IsReady)
{
Debug.LogWarning("Firebase 未初始化完成,丢弃本次支付打点");
return;
}
Debug.Log($"AppLovin 支付收入: {value} USD");
// var impressionParameters = new[] {
// new Firebase.Analytics.Parameter("value", value),
// new Firebase.Analytics.Parameter("currency", "USD"), // All AppLovin revenue is sent in USD
// };
//
// Firebase.Analytics.FirebaseAnalytics.LogEvent("purchase", impressionParameters);
// 上报到 Firebase 保持标准格式
var parameters = new[] {
new Parameter(FirebaseAnalytics.ParameterValue, value),
new Parameter(FirebaseAnalytics.ParameterCurrency, "USD")
};
FirebaseAnalytics.LogEvent(FirebaseAnalytics.EventPurchase, parameters);
Debug.Log("已上报 purchase 事件到 Firebase");
}
}
// using Firebase;
// using Firebase.Analytics;
// using Firebase.Extensions;
using UnityEngine;
namespace BallKingdomCrush
{
public class FireBaseManger: MonoBehaviour
{
public static bool IsReady { get; private set; } = false;
void Start()
{
// FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
// {
// if (task.Result == DependencyStatus.Available)
// {
// Debug.Log("Firebase 初始化成功");
//
// // 启用 Analytics
// FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);
//
// IsReady = true;
// }
// else
// {
// Debug.LogError("Firebase 依赖错误: " + task.Result);
// }
// });
}
/// <summary>
/// Max 广告的收益上传Firebase
/// </summary>
/// <param name="adUnitId"></param>
/// <param name="adInfo"></param>
public static void OnAdRevenuePaid(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
if (!IsReady)
{
Debug.LogWarning("Firebase 未初始化完成,丢弃本次广告打点");
return;
}
double revenue = adInfo.Revenue; // 收入,单位是美元 (USD)
string networkName = adInfo.NetworkName;
string adFormat = adInfo.AdFormat;
string adUnitIdentifier = adInfo.AdUnitIdentifier;
Debug.Log($"AppLovin 广告收入: {revenue} USD, 网络: {networkName}, 广告位: {adUnitId}");
// // 上报到 Firebase
// var impressionParameters = new[] {
// new Firebase.Analytics.Parameter("ad_platform", "AppLovin"),
// new Firebase.Analytics.Parameter("ad_source", networkName),
// new Firebase.Analytics.Parameter("ad_unit_name", adUnitIdentifier),
// new Firebase.Analytics.Parameter("ad_format", adFormat),
// new Firebase.Analytics.Parameter("value", revenue),
// new Firebase.Analytics.Parameter("currency", "USD"), // All AppLovin revenue is sent in USD
// };
// Firebase.Analytics.FirebaseAnalytics.LogEvent("ad_impression", impressionParameters);
Debug.Log("已上报 ad_impression 事件到 Firebase");
}
/// <summary>
/// 支付的收益上传Firebase
/// </summary>
public static void OnPayRevenueEvent(double value)
{
if (!IsReady)
{
Debug.LogWarning("Firebase 未初始化完成,丢弃本次支付打点");
return;
}
Debug.Log($"AppLovin 支付收入: {value} USD");
// var impressionParameters = new[] {
// new Firebase.Analytics.Parameter("value", value),
// new Firebase.Analytics.Parameter("currency", "USD"), // All AppLovin revenue is sent in USD
// };
//
// Firebase.Analytics.FirebaseAnalytics.LogEvent("purchase", impressionParameters);
// 上报到 Firebase 保持标准格式
// var parameters = new[] {
// new Parameter(FirebaseAnalytics.ParameterValue, value),
// new Parameter(FirebaseAnalytics.ParameterCurrency, "USD")
// };
// FirebaseAnalytics.LogEvent(FirebaseAnalytics.EventPurchase, parameters);
Debug.Log("已上报 purchase 事件到 Firebase");
}
}
}
+167 -167
View File
@@ -1,167 +1,167 @@
using System;
using System.Collections.Generic;
using SGModule.MarkdownKit;
using SGModule.NetKit;
using SGModule.Common.Helper;
using UnityEngine;
using BallKingdomCrush;
using UNSDK;
public class LoveLegendRoot : MonoBehaviour
{
public void Awake()
{
#if UNITY_EDITOR || GAME_RELEASE
GameObject.Find("IngameDebugConsole").SetActive(false);
#endif
SdkConfigMgr.Init();
MaxADKit.Init();
OnLauncher();
TrackKit.TrackLoginFunnel(LoginFunnelEventType.Bootstrap);
BuildGMTool();
NetGmTool.Instance.Init();
}
public static void OnLauncher()
{
Language.LoadLocalizedText();
Language.Initialize();
AppObjConst.FrameGo = new GameObject($"{AppObjConst.FrameGoName}");
AppObjConst.FrameGo.AddComponent<LoveLegendCore>();
DontDestroyOnLoad(AppObjConst.FrameGo);
App.InitApplication(SuperApplication.Instance);
NetworkManager.haveSimCard = HasSIMCard();
MarkdownKit.Instance.LoadText("privacy", "https://official.piggyhydration.com/privacy.md");
MarkdownKit.Instance.LoadText("user", "https://official.piggyhydration.com/user.md");
}
private static string adInfoLabel = "";
private static void BuildGMTool()
{
GMTool.Instance.AddItem(new GMToolItem(GUIType.Separator, () => "测试工具"));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Separator, () => "测试工具"));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "清空签到记录",
s =>
{
DataMgr.SignState.Value = new List<long>();
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "测试签到",
s =>
{
DataMgr.SignState.Value.Add(GameHelper.GetNowTime() + (long)TimeSpan.FromDays(DataMgr.SignState.Value.Count).TotalSeconds);
DataMgr.SignState.Save();
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "打开礼包界面",
s =>
{
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PackrewardUI_Open, true);
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "加广告次数+1",
s =>
{
var adNums = AdExchangeManager.Instance.GetLookRewardADNum();
adNums += 1;
AdExchangeManager.Instance.SetLookRewardADNum(adNums);
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "加广告次数+10",
s =>
{
var adNums = AdExchangeManager.Instance.GetLookRewardADNum();
adNums += 10;
AdExchangeManager.Instance.SetLookRewardADNum(adNums);
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "金币测试 +1000000",
s =>
{
DataMgr.Coin.Value += 1000000;
adInfoLabel += $"金币测试+1000000 当前金币: {DataMgr.Coin.Value}\n";
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "等级 +5",
s =>
{
DataMgr.GameLevel.Value += 5;
adInfoLabel += $"等级 +5 当前等级: {DataMgr.GameLevel.Value}\n";
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "客户端日志上传",
s =>
{
ErrorLogKit.Send("error", "客户端日志上传", "GM工具点击测试", SuperApplication.Instance.attribution);
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "广告ID信息打印",
s =>
{
adInfoLabel += $"Max token: {MaxADKit.SDKKey} \n 激励广告Id: {MaxADKit.rewardedADUnitID} \n 插屏广告Id: {MaxADKit.interstitialADUnitID} \n";
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Label, () => $"{DataMgr.Ticket} 类型测试"));
// 来显示 adInfoLabel 的内容
GMTool.Instance.AddItem(new GMToolItem(GUIType.Label, () => adInfoLabel));
}
public static bool HasSIMCard()
{
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
// 获取当前Activity
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
// 获取TelephonyManager
AndroidJavaObject telephonyManager = currentActivity.Call<AndroidJavaObject>("getSystemService", "phone");
if (telephonyManager == null)
{
Debug.Log("无法获取TelephonyManager,可能设备不支持电话功能。");
return false;
}
// 获取SIM卡状态
int simState = telephonyManager.Call<int>("getSimState");
Debug.Log("simState-------" + simState);
// 判断SIM卡状态
switch (simState)
{
case 1: // SIM_STATE_ABSENT
return false;
case 2: // sim_STATE_PIN_REQUIRED
case 3: // SIM_STATE_LOCKED
case 4: // SIM_STATE_NETWORK_LOCKED
case 5: // SIM_STATE_READY
return true;
default:
return false;
}
}
catch (System.Exception e)
{
Debug.LogError("检查SIM卡时出错: " + e.Message);
return false;
}
#else
return false;
#endif
}
}
using System;
using System.Collections.Generic;
using SGModule.MarkdownKit;
using SGModule.NetKit;
using SGModule.Common.Helper;
using UnityEngine;
using BallKingdomCrush;
using UNSDK;
public class LoveLegendRoot : MonoBehaviour
{
public void Awake()
{
#if UNITY_EDITOR || GAME_RELEASE
// GameObject.Find("IngameDebugConsole").SetActive(false);
#endif
SdkConfigMgr.Init();
MaxADKit.Init();
OnLauncher();
TrackKit.TrackLoginFunnel(LoginFunnelEventType.Bootstrap);
BuildGMTool();
NetGmTool.Instance.Init();
}
public static void OnLauncher()
{
Language.LoadLocalizedText();
Language.Initialize();
AppObjConst.FrameGo = new GameObject($"{AppObjConst.FrameGoName}");
AppObjConst.FrameGo.AddComponent<LoveLegendCore>();
DontDestroyOnLoad(AppObjConst.FrameGo);
App.InitApplication(SuperApplication.Instance);
NetworkManager.haveSimCard = HasSIMCard();
MarkdownKit.Instance.LoadText("privacy", "https://official.piggyhydration.com/privacy.md");
MarkdownKit.Instance.LoadText("user", "https://official.piggyhydration.com/user.md");
}
private static string adInfoLabel = "";
private static void BuildGMTool()
{
GMTool.Instance.AddItem(new GMToolItem(GUIType.Separator, () => "测试工具"));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Separator, () => "测试工具"));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "清空签到记录",
s =>
{
DataMgr.SignState.Value = new List<long>();
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "测试签到",
s =>
{
DataMgr.SignState.Value.Add(GameHelper.GetNowTime() + (long)TimeSpan.FromDays(DataMgr.SignState.Value.Count).TotalSeconds);
DataMgr.SignState.Save();
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "打开礼包界面",
s =>
{
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PackrewardUI_Open, true);
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "加广告次数+1",
s =>
{
var adNums = AdExchangeManager.Instance.GetLookRewardADNum();
adNums += 1;
AdExchangeManager.Instance.SetLookRewardADNum(adNums);
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "加广告次数+10",
s =>
{
var adNums = AdExchangeManager.Instance.GetLookRewardADNum();
adNums += 10;
AdExchangeManager.Instance.SetLookRewardADNum(adNums);
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "金币测试 +1000000",
s =>
{
DataMgr.Coin.Value += 1000000;
adInfoLabel += $"金币测试+1000000 当前金币: {DataMgr.Coin.Value}\n";
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "等级 +5",
s =>
{
DataMgr.GameLevel.Value += 5;
adInfoLabel += $"等级 +5 当前等级: {DataMgr.GameLevel.Value}\n";
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "客户端日志上传",
s =>
{
ErrorLogKit.Send("error", "客户端日志上传", "GM工具点击测试", SuperApplication.Instance.attribution);
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Button,
() => "广告ID信息打印",
s =>
{
adInfoLabel += $"Max token: {MaxADKit.SDKKey} \n 激励广告Id: {MaxADKit.rewardedADUnitID} \n 插屏广告Id: {MaxADKit.interstitialADUnitID} \n";
}));
GMTool.Instance.AddItem(new GMToolItem(GUIType.Label, () => $"{DataMgr.Ticket} 类型测试"));
// 来显示 adInfoLabel 的内容
GMTool.Instance.AddItem(new GMToolItem(GUIType.Label, () => adInfoLabel));
}
public static bool HasSIMCard()
{
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
// 获取当前Activity
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
// 获取TelephonyManager
AndroidJavaObject telephonyManager = currentActivity.Call<AndroidJavaObject>("getSystemService", "phone");
if (telephonyManager == null)
{
Debug.Log("无法获取TelephonyManager,可能设备不支持电话功能。");
return false;
}
// 获取SIM卡状态
int simState = telephonyManager.Call<int>("getSimState");
Debug.Log("simState-------" + simState);
// 判断SIM卡状态
switch (simState)
{
case 1: // SIM_STATE_ABSENT
return false;
case 2: // sim_STATE_PIN_REQUIRED
case 3: // SIM_STATE_LOCKED
case 4: // SIM_STATE_NETWORK_LOCKED
case 5: // SIM_STATE_READY
return true;
default:
return false;
}
}
catch (System.Exception e)
{
Debug.LogError("检查SIM卡时出错: " + e.Message);
return false;
}
#else
return false;
#endif
}
}
@@ -1,377 +1,378 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FairyGUI;
using FGUI.LG_secretAlbums;
using FGUI.ZM_Common_01;
using SGModule.Common.Helper;
using SGModule.NetKit;
using UnityEngine;
namespace BallKingdomCrush
{
public class SecretAlbumsUI : BaseUI
{
private const int MaxVisibleCount = 6; // 一屏显示6个
private const int PreloadCount = 2; // 上下各预加载一屏
private readonly Dictionary<int, bool> _fileIsExist = new();
private readonly Dictionary<int, GLoader> activeLoaders = new();
private SecretAlbumsUICtrl ctrl;
private SecretAlbumsModel model;
private com_scAlbums ui;
public SecretAlbumsUI(SecretAlbumsUICtrl ctrl) : base(ctrl)
{
uiName = UIConst.SecretAlbumsUI;
this.ctrl = ctrl;
}
protected override void SetUIInfo(UIInfo uiInfo)
{
uiInfo.packageName = "LG_secretAlbums";
uiInfo.assetName = "com_scAlbums";
uiInfo.layerType = UILayerType.Popup;
uiInfo.isNeedOpenAnim = false;
uiInfo.isNeedCloseAnim = false;
uiInfo.isNeedUIMask = true;
}
#region
protected override void OnInit()
{
//model = ModuleManager.Instance.GetModel(ModelConst.SecretAlbumsModel) as SecretAlbumsModel;
// 初始化GLoader池,设置最大缓存数
GLoaderPool.Instance.Init(null, 10, 464, 642);
}
protected override void OnClose()
{
// 1. 解除 UI 对 Loader 的引用
for (var i = 0; i < ui.sc_list.numChildren; i++)
{
var item = ui.sc_list.GetChildAt(i) as item_scalnums;
if (item != null && item.com_pic.picture != null) item.com_pic.picture = null; // 清掉 GLoader 引用
}
activeLoaders.Clear();
_fileIsExist.Clear();
GLoaderPool.Instance.DisposeAll();
TextureHelper.ClearMaterialPool();
// 强制卸载未使用的资源
// Resources.UnloadUnusedAssets();
MemoryManager.CleanMemoryMonitor();
}
protected override void OnBind()
{
ui = baseUI as FGUI.LG_secretAlbums.com_scAlbums;
}
private List<SecretAlbums> _secretData = new List<SecretAlbums>();
protected override void OnOpenBefore(object args)
{
if (Screen.safeArea.y != 0)
{
ui.btn_gold.y += 68;
ui.btn_close.y += 68;
ui.sc_list.y += 68;
}
var eventName = GameHelper.IsAdModelOfPay() ? ADEventTrack.AD_Event : ADEventTrack.MaxPayEvent;
TrackKit.SendEvent(eventName, ADEventTrack.Property.secret_albums_show);
_secretData = ConfigSystem.GetConfig<SecretAlbums>();
InitView();
}
protected override void OnOpen(object args)
{
}
protected override void OnHide()
{
}
protected override void OnDisplay(object args)
{
}
#endregion
#region
protected override void AddListener()
{
GameDispatcher.Instance.AddListener(GameMsg.UnlockSecretSuccess, UnlockSuccess);
GameDispatcher.Instance.AddListener(GameMsg.Gold_refresh, set101);
}
protected override void RemoveListener()
{
GameDispatcher.Instance.RemoveListener(GameMsg.UnlockSecretSuccess, UnlockSuccess);
GameDispatcher.Instance.RemoveListener(GameMsg.Gold_refresh, set101);
}
#endregion
void UnlockSuccess(object str = null)
{
ui.btn_gold.GetChild("text_gold").text = GameHelper.Get101Str();
ui.sc_list.itemRenderer = ItemRender;
ui.sc_list.numItems = _secretData.Count;
}
private void set101(object obj)
{
ui.btn_gold.GetChild("text_gold").text = GameHelper.Get101Str();
}
//初始化页面逻辑
private void InitView()
{
ui.btn_gold.GetChild("text_gold").text = GameHelper.Get101Str();
ui.btn_close.SetClick(CtrlCloseUI);
UnlockSuccess();
InitScroll();
}
private void InitScroll()
{
ui.sc_list.scrollPane.onScroll.Add(OnScrollUpdate);
ui.sc_list.scrollPane.onScrollEnd.Add(OnScrollEnd); // 保留结束时的整理
OnScrollEnd();
}
// 滑动过程中实时更新
private void OnScrollUpdate()
{
UpdateVisibleAndPreload();
}
// 核心刷新逻辑
private void UpdateVisibleAndPreload()
{
if (_secretData == null || _secretData.Count == 0) return;
var firstVisibleIndex = ui.sc_list.GetFirstChildInView();
var lastVisibleIndex = Mathf.Min(firstVisibleIndex + MaxVisibleCount - 1, ui.sc_list.numItems - 1);
var startIndex = Mathf.Max(0, firstVisibleIndex - PreloadCount);
var endIndex = Mathf.Min(ui.sc_list.numItems - 1, lastVisibleIndex + PreloadCount);
// 回收超出范围 loader
var keysToRemove = new List<int>();
foreach (var kv in activeLoaders)
{
var idx = kv.Key;
if (idx < startIndex || idx > endIndex)
{
GLoaderPool.Instance.ReturnLoader(kv.Value);
var oldItem = ui.sc_list.GetChildAt(idx) as item_scalnums;
if (oldItem != null) oldItem.com_pic.picture = null;
keysToRemove.Add(idx);
}
}
foreach (var k in keysToRemove) activeLoaders.Remove(k);
// 分配 loader 并加载图片
for (var i = startIndex; i <= endIndex; i++)
{
if (activeLoaders.ContainsKey(i)) continue;
var item = ui.sc_list.GetChildAt(i) as item_scalnums;
if (item == null) continue;
if (item.com_pic.picture != null && !item.com_pic.picture.isDisposed)
GLoaderPool.Instance.ReturnLoader(item.com_pic.picture);
var loader = GLoaderPool.Instance.GetLoader();
item.com_pic.picture = loader;
item.com_pic.AddChild(loader);
loader.SetSize(item.com_pic.width, item.com_pic.height);
_fileIsExist.TryGetValue(i, out var value);
if (!value)
{
var localPath = Path.Combine(TextureHelper.getResPath(), _secretData[i].Name + ".jpg");
if (File.Exists(localPath))
{
_fileIsExist[i] = true;
Debug.Log($"[SetImgLoader] 本地存在,直接加载 {_secretData[i].Name}");
CrazyAsyKit.StartCoroutine(TextureHelper.LoadTexture(_secretData[i].Name, loader, null,
"SecretAlbums/"));
}
else
{
_fileIsExist[i] = false;
}
}
else
{
CrazyAsyKit.StartCoroutine(TextureHelper.LoadTexture(_secretData[i].Name, loader, null,
"SecretAlbums/"));
}
activeLoaders[i] = loader;
}
// Debug.Log($"[ScrollUpdate] active loaders={activeLoaders.Count}, pool={GLoaderPool.Instance.GetPoolCount()}, inUse={GLoaderPool.Instance.GetInUseCount()}");
}
private void OnScrollEnd()
{
if (_secretData == null || _secretData.Count == 0) return;
var firstVisibleIndex = ui.sc_list.GetFirstChildInView();
var lastVisibleIndex = Mathf.Min(firstVisibleIndex + MaxVisibleCount - 1, ui.sc_list.numItems - 1);
var startIndex = Mathf.Max(0, firstVisibleIndex - PreloadCount);
var endIndex = Mathf.Min(ui.sc_list.numItems - 1, lastVisibleIndex + PreloadCount);
// Debug.Log($"[ScrollEnd] start index={startIndex} end index={endIndex}");
var tasks = new List<(GLoader loader, string fileName, Action<NTexture> callback, string folder, string localFolder)>();
// 分配 loader 并加载图片
for (var i = startIndex; i <= endIndex; i++)
{
_fileIsExist.TryGetValue(i, out var value);
if (value) continue;
var item = ui.sc_list.GetChildAt(i) as item_scalnums;
if (item == null) continue;
if (item.com_pic.picture != null && !item.com_pic.picture.isDisposed)
GLoaderPool.Instance.ReturnLoader(item.com_pic.picture);
var loader = GLoaderPool.Instance.GetLoader();
item.com_pic.picture = loader;
item.com_pic.AddChild(loader);
loader.SetSize(item.com_pic.width, item.com_pic.height);
var idx = i;
tasks.Add((loader, _secretData[i].Name, texture =>
{
if (texture != null) _fileIsExist[idx] = true;
}, "SecretAlbums/", FolderNames.SecretName));
activeLoaders[i] = loader;
}
if (tasks.Count > 0)
{
TextureHelper.SetImgLoaders(tasks);
}
}
private void ItemRender(int index, GObject obj)
{
var item = (item_scalnums)obj;
item.text_id.text = _secretData[index].id.ToString();
var isUnlock = DataMgr.SecretUnlockList.Value.Contains(index);
item.btn_unlock.pay_type.selectedIndex = _secretData[index].PayType;
if (_secretData[index].PayType == 0)
item.btn_unlock.title = GameHelper.getPrice((decimal)_secretData[index].DiscountPrice);
else if (_secretData[index].PayType == 1)
item.btn_unlock.title = _secretData[index].GoldCoins.ToString();
else if (_secretData[index].PayType == 2) item.btn_unlock.title = _secretData[index].AD + "AD";
if (isUnlock)
{
item.btn_unlock.pay_type.selectedIndex = 3;
if (_secretData[index].SubscribeUnlock == 1)
{
item.vip.selectedIndex = 2;
item.btn_unlock.pay_type.selectedIndex = 4;
}
item.btn_unlock.title = "GO";
}
else
{
if (_secretData[index].SubscribeUnlock == 1)
{
item.vip.selectedIndex = 1;
item.btn_unlock.pay_type.selectedIndex = 4;
}
}
item.btn_null.SetClick(GotoNext);
item.un_lock.selectedIndex = isUnlock ? 1 : 0;
item.btn_unlock.SetClick(GotoNext);
item.peple_num.text = GetPepleNum(_secretData[index].Quantity).ToString();
item.hot.selectedIndex = _secretData[index].HotType;
void GotoNext()
{
var da = _secretData;
var data = new AlbumPreviewData
{
Index = index,
State = _secretData[index].State,
Price = _secretData[index].Price,
PayType = _secretData[index].PayType,
SubscribeUnlock = _secretData[index].SubscribeUnlock,
DiscountPrice = _secretData[index].DiscountPrice,
Name = _secretData[index].Name,
Name2 = _secretData[index].Name2,
GoldCoins = _secretData[index].GoldCoins,
AD = _secretData[index].AD,
CD = _secretData[index].CD
};
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.SecretAlbumsNextUI_Open, data);
}
}
private int GetPepleNum(float quantity)
{
// 获取当前时间
DateTime now = DateTime.Now;
// 计算当天已经过去的分钟数(从凌晨 0 点开始算)
int minutesPassedToday = now.Hour * 60 + now.Minute;
// 计算人数
int num = Mathf.FloorToInt(quantity * minutesPassedToday);
return num;
}
}
public class AlbumPreviewData
{
public int[] State;
public int Index;
public string Name;
public float Price;
public int SubscribeUnlock;
public int PayType;
public float DiscountPrice;
public string Name2;
public int GoldCoins;
public int AD;
public int CD;
}
public enum UnlockPayType
{
Pay = 0,
Coin = 1,
Ad = 2,
None = 3,
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FairyGUI;
using FGUI.LG_secretAlbums;
using FGUI.ZM_Common_01;
using SGModule.Common.Helper;
using SGModule.NetKit;
using UnityEngine;
namespace BallKingdomCrush
{
public class SecretAlbumsUI : BaseUI
{
private const int MaxVisibleCount = 6; // 一屏显示6个
private const int PreloadCount = 2; // 上下各预加载一屏
private readonly Dictionary<int, bool> _fileIsExist = new();
private readonly Dictionary<int, GLoader> activeLoaders = new();
private SecretAlbumsUICtrl ctrl;
private SecretAlbumsModel model;
private com_scAlbums ui;
public SecretAlbumsUI(SecretAlbumsUICtrl ctrl) : base(ctrl)
{
uiName = UIConst.SecretAlbumsUI;
this.ctrl = ctrl;
}
protected override void SetUIInfo(UIInfo uiInfo)
{
uiInfo.packageName = "LG_secretAlbums";
uiInfo.assetName = "com_scAlbums";
uiInfo.layerType = UILayerType.Popup;
uiInfo.isNeedOpenAnim = false;
uiInfo.isNeedCloseAnim = false;
uiInfo.isNeedUIMask = true;
}
#region
protected override void OnInit()
{
//model = ModuleManager.Instance.GetModel(ModelConst.SecretAlbumsModel) as SecretAlbumsModel;
// 初始化GLoader池,设置最大缓存数
GLoaderPool.Instance.Init(null, 10, 464, 642);
}
protected override void OnClose()
{
// 1. 解除 UI 对 Loader 的引用
for (var i = 0; i < ui.sc_list.numChildren; i++)
{
var item = ui.sc_list.GetChildAt(i) as item_scalnums;
if (item != null && item.com_pic.picture != null) item.com_pic.picture = null; // 清掉 GLoader 引用
}
activeLoaders.Clear();
_fileIsExist.Clear();
GLoaderPool.Instance.DisposeAll();
TextureHelper.ClearMaterialPool();
// 强制卸载未使用的资源
// Resources.UnloadUnusedAssets();
MemoryManager.CleanMemoryMonitor();
}
protected override void OnBind()
{
ui = baseUI as FGUI.LG_secretAlbums.com_scAlbums;
}
private List<SecretAlbums> _secretData = new List<SecretAlbums>();
private List<SecretAlbums> _secretData1 = new List<SecretAlbums>();
protected override void OnOpenBefore(object args)
{
if (Screen.safeArea.y != 0)
{
ui.btn_gold.y += 68;
ui.btn_close.y += 68;
ui.sc_list.y += 68;
}
var eventName = GameHelper.IsAdModelOfPay() ? ADEventTrack.AD_Event : ADEventTrack.MaxPayEvent;
TrackKit.SendEvent(eventName, ADEventTrack.Property.secret_albums_show);
_secretData = ConfigSystem.GetConfig<SecretAlbums>();
InitView();
}
protected override void OnOpen(object args)
{
}
protected override void OnHide()
{
}
protected override void OnDisplay(object args)
{
}
#endregion
#region
protected override void AddListener()
{
GameDispatcher.Instance.AddListener(GameMsg.UnlockSecretSuccess, UnlockSuccess);
GameDispatcher.Instance.AddListener(GameMsg.Gold_refresh, set101);
}
protected override void RemoveListener()
{
GameDispatcher.Instance.RemoveListener(GameMsg.UnlockSecretSuccess, UnlockSuccess);
GameDispatcher.Instance.RemoveListener(GameMsg.Gold_refresh, set101);
}
#endregion
void UnlockSuccess(object str = null)
{
ui.btn_gold.GetChild("text_gold").text = GameHelper.Get101Str();
ui.sc_list.itemRenderer = ItemRender;
ui.sc_list.numItems = _secretData.Count;
}
private void set101(object obj)
{
ui.btn_gold.GetChild("text_gold").text = GameHelper.Get101Str();
}
//初始化页面逻辑
private void InitView()
{
ui.btn_gold.GetChild("text_gold").text = GameHelper.Get101Str();
ui.btn_close.SetClick(CtrlCloseUI);
UnlockSuccess();
InitScroll();
}
private void InitScroll()
{
ui.sc_list.scrollPane.onScroll.Add(OnScrollUpdate);
ui.sc_list.scrollPane.onScrollEnd.Add(OnScrollEnd); // 保留结束时的整理
OnScrollEnd();
}
// 滑动过程中实时更新
private void OnScrollUpdate()
{
UpdateVisibleAndPreload();
}
// 核心刷新逻辑
private void UpdateVisibleAndPreload()
{
if (_secretData == null || _secretData.Count == 0) return;
var firstVisibleIndex = ui.sc_list.GetFirstChildInView();
var lastVisibleIndex = Mathf.Min(firstVisibleIndex + MaxVisibleCount - 1, ui.sc_list.numItems - 1);
var startIndex = Mathf.Max(0, firstVisibleIndex - PreloadCount);
var endIndex = Mathf.Min(ui.sc_list.numItems - 1, lastVisibleIndex + PreloadCount);
// 回收超出范围 loader
var keysToRemove = new List<int>();
foreach (var kv in activeLoaders)
{
var idx = kv.Key;
if (idx < startIndex || idx > endIndex)
{
GLoaderPool.Instance.ReturnLoader(kv.Value);
var oldItem = ui.sc_list.GetChildAt(idx) as item_scalnums;
if (oldItem != null) oldItem.com_pic.picture = null;
keysToRemove.Add(idx);
}
}
foreach (var k in keysToRemove) activeLoaders.Remove(k);
// 分配 loader 并加载图片
for (var i = startIndex; i <= endIndex; i++)
{
if (activeLoaders.ContainsKey(i)) continue;
var item = ui.sc_list.GetChildAt(i) as item_scalnums;
if (item == null) continue;
if (item.com_pic.picture != null && !item.com_pic.picture.isDisposed)
GLoaderPool.Instance.ReturnLoader(item.com_pic.picture);
var loader = GLoaderPool.Instance.GetLoader();
item.com_pic.picture = loader;
item.com_pic.AddChild(loader);
loader.SetSize(item.com_pic.width, item.com_pic.height);
_fileIsExist.TryGetValue(i, out var value);
if (!value)
{
var localPath = Path.Combine(TextureHelper.getResPath(), _secretData[i].Name + ".jpg");
if (File.Exists(localPath))
{
_fileIsExist[i] = true;
Debug.Log($"[SetImgLoader] 本地存在,直接加载 {_secretData[i].Name}");
CrazyAsyKit.StartCoroutine(TextureHelper.LoadTexture(_secretData[i].Name, loader, null,
"SecretAlbums/"));
}
else
{
_fileIsExist[i] = false;
}
}
else
{
CrazyAsyKit.StartCoroutine(TextureHelper.LoadTexture(_secretData[i].Name, loader, null,
"SecretAlbums/"));
}
activeLoaders[i] = loader;
}
// Debug.Log($"[ScrollUpdate] active loaders={activeLoaders.Count}, pool={GLoaderPool.Instance.GetPoolCount()}, inUse={GLoaderPool.Instance.GetInUseCount()}");
}
private void OnScrollEnd()
{
if (_secretData == null || _secretData.Count == 0) return;
var firstVisibleIndex = ui.sc_list.GetFirstChildInView();
var lastVisibleIndex = Mathf.Min(firstVisibleIndex + MaxVisibleCount - 1, ui.sc_list.numItems - 1);
var startIndex = Mathf.Max(0, firstVisibleIndex - PreloadCount);
var endIndex = Mathf.Min(ui.sc_list.numItems - 1, lastVisibleIndex + PreloadCount);
// Debug.Log($"[ScrollEnd] start index={startIndex} end index={endIndex}");
var tasks = new List<(GLoader loader, string fileName, Action<NTexture> callback, string folder, string localFolder)>();
// 分配 loader 并加载图片
for (var i = startIndex; i <= endIndex; i++)
{
_fileIsExist.TryGetValue(i, out var value);
if (value) continue;
var item = ui.sc_list.GetChildAt(i) as item_scalnums;
if (item == null) continue;
if (item.com_pic.picture != null && !item.com_pic.picture.isDisposed)
GLoaderPool.Instance.ReturnLoader(item.com_pic.picture);
var loader = GLoaderPool.Instance.GetLoader();
item.com_pic.picture = loader;
item.com_pic.AddChild(loader);
loader.SetSize(item.com_pic.width, item.com_pic.height);
var idx = i;
tasks.Add((loader, _secretData[i].Name, texture =>
{
if (texture != null) _fileIsExist[idx] = true;
}, "SecretAlbums/", FolderNames.SecretName));
activeLoaders[i] = loader;
}
if (tasks.Count > 0)
{
TextureHelper.SetImgLoaders(tasks);
}
}
private void ItemRender(int index, GObject obj)
{
var item = (item_scalnums)obj;
item.text_id.text = _secretData[index].id.ToString();
var isUnlock = DataMgr.SecretUnlockList.Value.Contains(index);
item.btn_unlock.pay_type.selectedIndex = _secretData[index].PayType;
if (_secretData[index].PayType == 0)
item.btn_unlock.title = GameHelper.getPrice((decimal)_secretData[index].DiscountPrice);
else if (_secretData[index].PayType == 1)
item.btn_unlock.title = _secretData[index].GoldCoins.ToString();
else if (_secretData[index].PayType == 2) item.btn_unlock.title = _secretData[index].AD + "AD";
if (isUnlock)
{
item.btn_unlock.pay_type.selectedIndex = 3;
if (_secretData[index].SubscribeUnlock == 1)
{
item.vip.selectedIndex = 2;
item.btn_unlock.pay_type.selectedIndex = 4;
}
item.btn_unlock.title = "GO";
}
else
{
if (_secretData[index].SubscribeUnlock == 1)
{
item.vip.selectedIndex = 1;
item.btn_unlock.pay_type.selectedIndex = 4;
}
}
item.btn_null.SetClick(GotoNext);
item.un_lock.selectedIndex = isUnlock ? 1 : 0;
item.btn_unlock.SetClick(GotoNext);
item.peple_num.text = GetPepleNum(_secretData[index].Quantity).ToString();
item.hot.selectedIndex = _secretData[index].HotType;
void GotoNext()
{
var da = _secretData;
var data = new AlbumPreviewData
{
Index = index,
State = _secretData[index].State,
Price = _secretData[index].Price,
PayType = _secretData[index].PayType,
SubscribeUnlock = _secretData[index].SubscribeUnlock,
DiscountPrice = _secretData[index].DiscountPrice,
Name = _secretData[index].Name,
Name2 = _secretData[index].Name2,
GoldCoins = _secretData[index].GoldCoins,
AD = _secretData[index].AD,
CD = _secretData[index].CD
};
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.SecretAlbumsNextUI_Open, data);
}
}
private int GetPepleNum(float quantity)
{
// 获取当前时间
DateTime now = DateTime.Now;
// 计算当天已经过去的分钟数(从凌晨 0 点开始算)
int minutesPassedToday = now.Hour * 60 + now.Minute;
// 计算人数
int num = Mathf.FloorToInt(quantity * minutesPassedToday);
return num;
}
}
public class AlbumPreviewData
{
public int[] State;
public int Index;
public string Name;
public float Price;
public int SubscribeUnlock;
public int PayType;
public float DiscountPrice;
public string Name2;
public int GoldCoins;
public int AD;
public int CD;
}
public enum UnlockPayType
{
Pay = 0,
Coin = 1,
Ad = 2,
None = 3,
}
}
+177 -149
View File
@@ -1,150 +1,178 @@
using System;
using System.Collections.Generic;
using System.Linq;
using IgnoreOPS;
using SGModule.Common.Extensions;
using SGModule.Common.Helper;
using SGModule.ConfigLoader;
using SGModule.NetKit;
using UnityEngine;
using CommonModel = IgnoreOPS.CommonModel;
namespace BallKingdomCrush
{
public class ConfigSystem : BaseSystem
{
public static string web_through_str;
public ConfigSystem(bool isAutoInit = true)
{
if (isAutoInit)
{
Init();
}
}
public sealed override void Init()
{
base.Init();
AddListener();
}
private void AddListener()
{
NetworkDispatcher.Instance.AddListener(NetworkMsg.GetConfig, OnGetConfig);
}
private void RemoveListener()
{
NetworkDispatcher.Instance.RemoveListener(NetworkMsg.GetConfig, OnGetConfig);
}
private void OnGetConfig(object obj)
{
TrackKit.TrackLoginFunnel(LoginFunnelEventType.LoadBegin); //加载开始打点
var loginModel = LoginKit.Instance.LoginModel;
Log.Info("Config", $"服务器传过来的配置表:{loginModel.Setting}");
ConfigLoader.Instance.Init(new ConfigInitOptions
{
Setting = loginModel.Setting,
CdnUrl = loginModel.CdnURL,
OnComplete = state =>
{
Debug.Log($"配置加载状态{state}");
if (state == ConfigLoaderState.Successful)
{
ReloadConfig();
}
},
OnError = (errorName, message) => { Debug.LogError($"配置解析错误 {errorName} 错误信息:{message}"); },
OnHandleUnmarkedConfig = ParseGameConfig
});
}
/// <summary>
/// 重新加载配置
/// </summary>
/// <param name="json"></param>
private void ReloadConfig()
{
TrackKit.TrackLoginFunnel(LoginFunnelEventType.LoadFinish); //加载完成打点
ParseGameConfig();
TextureHelper.imgUrl = LoginKit.Instance.LoginModel.CdnURL + "/" + ConfigSystem.GetCommonConf().ResVersion + "/";
LiveVideoManager.videoBaseUrl = LoginKit.Instance.LoginModel.CdnURL + "/" + ConfigSystem.GetCommonConf().ResVersion + "/";
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetLoadingUI_Close);
AppDispatcher.Instance.Dispatch(AppMsg.LoginInit);
CtrlDispatcher.Instance.Dispatch(CtrlMsg.Game_StartBefore);
SaveingPotHelper.ResetHistory();
}
#region
private void ParseGameConfig()
{
var gameConfigModel = new GameConfigModel();
foreach (var key in ConfigLoader.Instance.GetJsonKeys())
{
if (!key.StartsWith("GameBoard"))
{
continue;
}
// 提取 boardIndex
var boardIndex = 1;
var parts = key.Split('_');
if (parts.Length > 1 && int.TryParse(parts[1], out var parsed))
{
boardIndex = parsed;
}
// 获取 json 并反序列化
if (ConfigLoader.Instance.TryGetJsonValue(key, out var gameboardJson))
{
try
{
var gameBoards = gameboardJson.As<List<GameBoard>>();
if (gameBoards != null)
{
gameConfigModel.game_conf[boardIndex] = gameBoards;
}
else
{
Log.ConfigLoader.Warning($"GameBoard 配置 {key} 反序列化为空");
}
}
catch (Exception ex)
{
Log.ConfigLoader.Error($"GameBoard 配置 {key} 反序列化失败: {ex.Message}");
}
}
}
ConfigLoader.Instance.AddConfig(gameConfigModel);
}
#endregion
public static CommonModel GetCommonConf()
{
return ConfigLoader.Instance.GetConfig<CommonModel>();
}
public static List<T> GetConfig<T>() where T : class
{
return ConfigLoader.Instance.GetConfig<List<T>>() ?? new List<T>();
}
public override void Dispose()
{
base.Dispose();
RemoveListener();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using IgnoreOPS;
using SGModule.Common.Extensions;
using SGModule.Common.Helper;
using SGModule.ConfigLoader;
using SGModule.NetKit;
using UnityEngine;
using CommonModel = IgnoreOPS.CommonModel;
namespace BallKingdomCrush
{
public class ConfigSystem : BaseSystem
{
public static string web_through_str;
public ConfigSystem(bool isAutoInit = true)
{
if (isAutoInit)
{
Init();
}
}
public sealed override void Init()
{
base.Init();
AddListener();
}
private void AddListener()
{
NetworkDispatcher.Instance.AddListener(NetworkMsg.GetConfig, OnGetConfig);
}
private void RemoveListener()
{
NetworkDispatcher.Instance.RemoveListener(NetworkMsg.GetConfig, OnGetConfig);
}
private void OnGetConfig(object obj)
{
TrackKit.TrackLoginFunnel(LoginFunnelEventType.LoadBegin); //加载开始打点
var loginModel = LoginKit.Instance.LoginModel;
Log.Info("Config", $"服务器传过来的配置表:{loginModel.Setting}");
ConfigLoader.Instance.Init(new ConfigInitOptions
{
Setting = loginModel.Setting,
CdnUrl = loginModel.CdnURL,
OnComplete = state =>
{
Debug.Log($"配置加载状态{state}");
if (state == ConfigLoaderState.Successful)
{
ReloadConfig();
}
},
OnError = (errorName, message) => { Debug.LogError($"配置解析错误 {errorName} 错误信息:{message}"); },
OnHandleUnmarkedConfig = ParseGameConfig
});
}
/// <summary>
/// 重新加载配置
/// </summary>
/// <param name="json"></param>
private void ReloadConfig()
{
var CdnURL = "https://asserts.minskyfun.top";
TrackKit.TrackLoginFunnel(LoginFunnelEventType.LoadFinish); //加载完成打点
ParseGameConfig();
TextureHelper.imgUrl = CdnURL + "/" + ConfigSystem.GetCommonConf().ResVersion + "/";
LiveVideoManager.videoBaseUrl = CdnURL + "/" + ConfigSystem.GetCommonConf().ResVersion + "/";
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetLoadingUI_Close);
AppDispatcher.Instance.Dispatch(AppMsg.LoginInit);
CtrlDispatcher.Instance.Dispatch(CtrlMsg.Game_StartBefore);
SaveingPotHelper.ResetHistory();
}
#region
private void ParseGameConfig()
{
var gameConfigModel = new GameConfigModel();
foreach (var key in ConfigLoader.Instance.GetJsonKeys())
{
if (!key.StartsWith("GameBoard"))
{
continue;
}
// 提取 boardIndex
var boardIndex = 1;
var parts = key.Split('_');
if (parts.Length > 1 && int.TryParse(parts[1], out var parsed))
{
boardIndex = parsed;
}
// 获取 json 并反序列化
if (ConfigLoader.Instance.TryGetJsonValue(key, out var gameboardJson))
{
try
{
var gameBoards = gameboardJson.As<List<GameBoard>>();
if (gameBoards != null)
{
gameConfigModel.game_conf[boardIndex] = gameBoards;
}
else
{
Log.ConfigLoader.Warning($"GameBoard 配置 {key} 反序列化为空");
}
}
catch (Exception ex)
{
Log.ConfigLoader.Error($"GameBoard 配置 {key} 反序列化失败: {ex.Message}");
}
}
}
ConfigLoader.Instance.AddConfig(gameConfigModel);
}
#endregion
public static CommonModel GetCommonConf()
{
return ConfigLoader.Instance.GetConfig<CommonModel>();
}
public static List<T> GetConfig<T>() where T : class
{
return ConfigLoader.Instance.GetConfig<List<T>>() ?? new List<T>();
}
private static List<T> GetConfigWithOrganicFallback<T, TOrganic>() where T : class
{
if (GameHelper.IsGiftSwitch() && SuperApplication.Instance.attribution == "organic")
{
var organicConfig = ConfigLoader.Instance.GetConfig<List<TOrganic>>();
if (organicConfig != null)
{
return organicConfig.Cast<T>().ToList();
}
}
return GetConfig<T>();
}
public static List<Live> GetLiveConfig()
{
return GetConfigWithOrganicFallback<Live, Live_A>();
}
public static List<SecretAlbums> GetSecretAlbumsConfig()
{
return GetConfigWithOrganicFallback<SecretAlbums, SecretAlbums_A>();
}
public override void Dispose()
{
base.Dispose();
RemoveListener();
}
}
}
+101 -96
View File
@@ -1,96 +1,101 @@
using System;
using IgnoreOPS;
using SGModule.Common.Extensions;
using SGModule.Common.Helper;
using SGModule.NetKit;
namespace BallKingdomCrush {
public class LoginSystem : BaseSystem {
private int loginCount = 0;
private bool _isLogin = false;
private TimerTask timerTask = null;
public LoginSystem(bool isAutoInit = true) {
if (isAutoInit) {
Init();
}
}
public sealed override void Init() {
base.Init();
InitData();
AddListener();
}
private void InitData() {
}
private void AddListener() {
NetworkDispatcher.Instance.AddListener(NetworkMsg.Login, RequestLogin);
}
private void RemoveListener() {
NetworkDispatcher.Instance.RemoveListener(NetworkMsg.Login, RequestLogin);
}
private void RequestLogin(object obj = null) {
// if (!GameHelper.IsConnect())
// {
// LoginFail();
// }
// else
// {
if (_isLogin) return;
_isLogin = true;
TrackKit.TrackLoginFunnel(LoginFunnelEventType.LoginSend);
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetworkErrorTipsUI_Open);
Log.Info("login request", $"attribution: {SuperApplication.Instance.attribution}, haveSimCard: {NetworkManager.haveSimCard}");
LoginKit.Instance.LoginRequest(SuperApplication.Instance.attribution.ToLower(), NetworkManager.haveSimCard, (isSuccess, loginData) => {
TrackKit.TrackLoginFunnel(LoginFunnelEventType.LoginRecv, isSuccess ? "success" : "fail");
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetworkErrorTipsUI_Close);
if (isSuccess)
{
// AB上传 BI
BIManager.Instance.TrackABConfig(loginData.IsMagic ? 30 : 15);
TextureHelper.imgUrl = loginData.CdnURL + "/encrypt/image/";
LiveVideoManager.videoBaseUrl = loginData.CdnURL + "/encrypt/video/";
DateTimeManager.Instance.SetServerCurrTimestamp(loginData.LoginTime);
NetworkDispatcher.Instance.Dispatch(NetworkMsg.GetPlayData);
MaxADKit.SetUserID(loginData.Uid.As<string>());
}
else
{
LoginFail();
}
});
// }
}
private static void LoginFail()
{
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetLoadingUI_Close);
void OnFail() {
NetworkDispatcher.Instance.Dispatch(NetworkMsg.Login);
}
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.TipsViewUI_Open, (Action) OnFail);
}
public override void Dispose() {
base.Dispose();
RemoveListener();
}
}
}
using System;
using IgnoreOPS;
using SGModule.Common.Extensions;
using SGModule.Common.Helper;
using SGModule.NetKit;
using UnityEngine;
namespace BallKingdomCrush {
public class LoginSystem : BaseSystem {
private int loginCount = 0;
private bool _isLogin = false;
private TimerTask timerTask = null;
public LoginSystem(bool isAutoInit = true) {
if (isAutoInit) {
Init();
}
}
public sealed override void Init() {
base.Init();
InitData();
AddListener();
}
private void InitData() {
}
private void AddListener() {
NetworkDispatcher.Instance.AddListener(NetworkMsg.Login, RequestLogin);
}
private void RemoveListener() {
NetworkDispatcher.Instance.RemoveListener(NetworkMsg.Login, RequestLogin);
}
private void RequestLogin(object obj = null) {
// if (!GameHelper.IsConnect())
// {
// LoginFail();
// }
// else
// {
if (_isLogin) return;
_isLogin = true;
TrackKit.TrackLoginFunnel(LoginFunnelEventType.LoginSend);
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetworkErrorTipsUI_Open);
Log.Info("login request", $"attribution: {SuperApplication.Instance.attribution}, haveSimCard: {NetworkManager.haveSimCard}");
LoginKit.Instance.LoginRequest(SuperApplication.Instance.attribution.ToLower(), NetworkManager.haveSimCard, (isSuccess, loginData) => {
TrackKit.TrackLoginFunnel(LoginFunnelEventType.LoginRecv, isSuccess ? "success" : "fail");
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetworkErrorTipsUI_Close);
if (isSuccess)
{
Debug.Log($"loginData.CdnURL======={loginData.CdnURL}");
// AB上传 BI
BIManager.Instance.TrackABConfig(loginData.IsMagic ? 30 : 15);
// loginData.CdnURL = "https://asserts.minskyfun.top";
// TextureHelper.imgUrl = loginData.CdnURL + "/encrypt/image/";
// LiveVideoManager.videoBaseUrl = loginData.CdnURL + "/encrypt/video/";
DateTimeManager.Instance.SetServerCurrTimestamp(loginData.LoginTime);
NetworkDispatcher.Instance.Dispatch(NetworkMsg.GetPlayData);
MaxADKit.SetUserID(loginData.Uid.As<string>());
}
else
{
LoginFail();
}
});
// }
}
private static void LoginFail()
{
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetLoadingUI_Close);
void OnFail() {
NetworkDispatcher.Instance.Dispatch(NetworkMsg.Login);
}
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.TipsViewUI_Open, (Action) OnFail);
}
public override void Dispose() {
base.Dispose();
RemoveListener();
}
}
}