先修复一下,错误的场景 删除不必要的钓场资产 修复into场景 update:更新meta文件,修复报错 update:修复资源 修复第一章节建造 修复建造第三章 update:删除多余内容 update:更新README.md update:还原图标 update:更新README update:更新配置
371 lines
14 KiB
C#
371 lines
14 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using asap.core;
|
||
using SimpleJSON;
|
||
using UnityEngine;
|
||
using UnityEngine.Networking;
|
||
|
||
public static class ConfigExtension
|
||
{
|
||
private const string defaultconfig = "{\"StaticResURL\":\"https://sls-cloudfunction-ap-beijing-code-1305151099.cos.ap-beijing.myqcloud.com/mini/0_47\",\"PlayFabTitle\":\"108EE8\",\"Origin_Addressable_URL\":\"https://sls-cloudfunction-ap-beijing-code-1305151099.cos.ap-beijing.myqcloud.com/mini/0_47/Android\",\"HeartBeat\":300,\"CustomID\":\"{{input}}\",\"GM\":\"1\",\"FuncUrl\":\"http://62.234.191.215:7071\",\"FuncKey\":\"testKey\",\"Ver\":\"0.47.2f4aa9f\"}";
|
||
|
||
private static string RemoteConfigUrl { get; set; }
|
||
|
||
public static void Rest(this IConfig config)
|
||
{
|
||
RemoteConfigUrl = null;
|
||
}
|
||
|
||
public static async Task<bool> InitConfig(this IConfig config)
|
||
{
|
||
JSONNode streamingAssetConfig = null;
|
||
JSONNode persistConfig = null;
|
||
bool isSuccessLoadRemoteConfigFile = true;
|
||
|
||
if (RemoteConfigUrl == null)
|
||
{
|
||
streamingAssetConfig = GetStreamingAssetConfig();
|
||
persistConfig = GetPersistConfig();
|
||
}
|
||
|
||
if (RemoteConfigUrl == null)
|
||
{
|
||
var staticResURL = GConstant.V_Static_Res_URL;
|
||
if (ChannelManager.IsRustoreStore)
|
||
staticResURL = GConstant.V_Static_Res_URL_RU;
|
||
|
||
RemoteConfigUrl = string.Format(staticResURL, VersionTool.PackVer);
|
||
}
|
||
|
||
JSONNode remoteConfig = await GetRemoteConfig();
|
||
|
||
if (remoteConfig == null)
|
||
{
|
||
Debug.LogWarning($"[GConfig] Remote config download failed, using default config");
|
||
remoteConfig = JSON.Parse(defaultconfig);
|
||
remoteConfig["Ver"] = VersionTool.FromLocal().ToVerString();
|
||
isSuccessLoadRemoteConfigFile = false;
|
||
}
|
||
else
|
||
{
|
||
Debug.Log($"[GConfig] Remote config downloaded: Ver={remoteConfig["Ver"]}, StaticResURL={remoteConfig["StaticResURL"]}");
|
||
}
|
||
|
||
foreach (var element in remoteConfig)
|
||
{
|
||
config.Set(element.Key, element.Value.Value);
|
||
}
|
||
|
||
if (streamingAssetConfig != null)
|
||
{
|
||
foreach (var element in streamingAssetConfig)
|
||
{
|
||
config.Set(element.Key, element.Value.Value);
|
||
}
|
||
}
|
||
|
||
if (persistConfig != null)
|
||
{
|
||
foreach (var element in persistConfig)
|
||
{
|
||
config.Set(element.Key, element.Value.Value);
|
||
}
|
||
}
|
||
|
||
config.Set(GConstant.K_Static_Res_URL, RemoteConfigUrl);
|
||
|
||
Debug.Log($"[GConfig] Final config: Ver={config.Get(GConstant.K_Ver, "N/A")}, StaticResURL={RemoteConfigUrl}, isSuccessLoadRemote={isSuccessLoadRemoteConfigFile}");
|
||
|
||
return isSuccessLoadRemoteConfigFile;
|
||
}
|
||
|
||
|
||
private static readonly float[] timeoutValues = new float[] { 1, 2, 2 };
|
||
|
||
public static async Task<JSONNode> GetRemoteConfig()
|
||
{
|
||
UnityEngine.Assertions.Assert.IsNotNull(RemoteConfigUrl, "Config is not inited");
|
||
|
||
await Awaiters.NextFrame;
|
||
|
||
var maxRetryTimes = timeoutValues.Length;
|
||
|
||
for (int retryTime = 0; retryTime < maxRetryTimes; retryTime++)
|
||
{
|
||
var rawConfig = await DoGetRawConfigUWR(timeoutValues[retryTime], retryTime, maxRetryTimes);
|
||
if (!string.IsNullOrEmpty(rawConfig))
|
||
{
|
||
Debug.Log($"<color=orange>Load remote config success {retryTime + 1}/{maxRetryTimes}</color>");
|
||
return JSON.Parse(rawConfig);
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private static async Task<string> DoGetRawConfigUWR(float timeoutInSec, int retryTimes, int maxRetryTimes)
|
||
{
|
||
var requestUrl = $"{RemoteConfigUrl}/{GConstant.V_Remote_Config_Path}";
|
||
Debug.Log($"[GConfig] Requesting remote config: {requestUrl}");
|
||
using (var req = UnityWebRequest.Get(requestUrl))
|
||
{
|
||
var stopwatch = new System.Diagnostics.Stopwatch();
|
||
var cts = new CancellationTokenSource();
|
||
cts.CancelAfter(TimeSpan.FromSeconds(timeoutInSec));
|
||
var ct = cts.Token;
|
||
stopwatch.Start();
|
||
req.timeout = (int)timeoutInSec;
|
||
req.SetRequestHeader("Accept", "application/json");
|
||
var op = req.SendWebRequest();
|
||
try
|
||
{
|
||
while (!op.isDone && !ct.IsCancellationRequested)
|
||
{
|
||
await Awaiters.NextFrame;
|
||
}
|
||
ct.ThrowIfCancellationRequested();
|
||
stopwatch.Stop();
|
||
|
||
if (req.result == UnityWebRequest.Result.Success)
|
||
{
|
||
Debug.Log($"[GConfig] Remote config raw response length={req.downloadHandler.text.Length}");
|
||
return req.downloadHandler.text;
|
||
}
|
||
|
||
#if AGG
|
||
using (var e = GEvent.TackEvent("retry"))
|
||
{
|
||
e.AddContent("type", "config");
|
||
e.AddContent("duration_ms", stopwatch.ElapsedMilliseconds);
|
||
e.AddContent("reason", req.result.ToString());
|
||
e.AddContent("skip", retryTimes >= maxRetryTimes - 1);
|
||
e.AddContent("error", req.error);
|
||
}
|
||
#endif // AGG
|
||
|
||
Debug.LogWarning($"Load remote config failed {req.result.ToString()} {req.error} {retryTimes + 1}/{maxRetryTimes}");
|
||
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
req.Abort();
|
||
stopwatch.Stop();
|
||
|
||
#if AGG
|
||
using (var e = GEvent.TackEvent("retry"))
|
||
{
|
||
e.AddContent("type", "config");
|
||
e.AddContent("duration_ms", stopwatch.ElapsedMilliseconds);
|
||
e.AddContent("reason", "cancel");
|
||
e.AddContent("skip", retryTimes >= maxRetryTimes - 1);
|
||
e.AddContent("error", req.error ?? "cancel");
|
||
}
|
||
#endif // AGG
|
||
|
||
Debug.LogWarning($"Load remote config cancel {req.result.ToString()} {req.error} {retryTimes + 1}/{maxRetryTimes}");
|
||
|
||
}
|
||
finally
|
||
{
|
||
cts.Dispose();
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
private static async Task<string> DoGetRawConfig(float timeoutInSec, int retryTimes)
|
||
{
|
||
var timeout = TimeSpan.FromSeconds(timeoutInSec);
|
||
var handler = new System.Net.Http.HttpClientHandler(){
|
||
SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
|
||
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }
|
||
};
|
||
using (var httpClient = new System.Net.Http.HttpClient(handler))
|
||
{
|
||
httpClient.Timeout = timeout;
|
||
var stopwatch = new System.Diagnostics.Stopwatch();
|
||
|
||
try
|
||
{
|
||
stopwatch.Start();
|
||
var respon = await httpClient.GetAsync($"{RemoteConfigUrl}/{GConstant.V_Remote_Config_Path}");
|
||
stopwatch.Stop();
|
||
|
||
if (respon.IsSuccessStatusCode)
|
||
{
|
||
string remoteConfigStr = await respon.Content.ReadAsStringAsync();
|
||
await Awaiters.NextFrame;
|
||
return Decrypt(remoteConfigStr);
|
||
}
|
||
else
|
||
{
|
||
var elapsed = stopwatch.ElapsedMilliseconds;
|
||
Debug.LogWarning($"Load remote config failed {respon.StatusCode.ToString()}");
|
||
#if AGG
|
||
using (var e = GEvent.TackEvent("retry"))
|
||
{
|
||
e.AddContent("type", "config");
|
||
e.AddContent("duration_ms", elapsed);
|
||
e.AddContent("reason", respon.StatusCode.ToString());
|
||
e.AddContent("skip", retryTimes >= 2);
|
||
e.AddContent("error", "http_request_failed");
|
||
}
|
||
#endif//AGG
|
||
}
|
||
}
|
||
catch (System.Net.Http.HttpRequestException httpEx)
|
||
{
|
||
if (stopwatch.IsRunning)
|
||
stopwatch.Stop();
|
||
var elapsed = stopwatch.Elapsed;
|
||
|
||
var errorMessage = $"HTTP request failed: {httpEx.Message}";
|
||
if (httpEx.InnerException != null)
|
||
{
|
||
errorMessage += $" Inner: {httpEx.InnerException.Message}";
|
||
if(httpEx.InnerException.InnerException != null)
|
||
{
|
||
errorMessage += $" InnerInner: {httpEx.InnerException.InnerException.Message}";
|
||
}
|
||
}
|
||
Debug.LogWarning(errorMessage);
|
||
|
||
#if AGG
|
||
using (var e = GEvent.TackEvent("retry"))
|
||
{
|
||
e.AddContent("type", "config");
|
||
e.AddContent("duration_ms", elapsed.TotalMilliseconds);
|
||
e.AddContent("reason", "httpEx");
|
||
e.AddContent("skip", retryTimes >= 2);
|
||
e.AddContent("error", errorMessage);
|
||
}
|
||
#endif//AGG
|
||
}
|
||
catch (System.Threading.Tasks.TaskCanceledException timeoutEx)
|
||
{
|
||
if (stopwatch.IsRunning)
|
||
stopwatch.Stop();
|
||
var elapsed = stopwatch.Elapsed;
|
||
|
||
Debug.LogWarning($"Request timeout after {timeoutInSec}s: {timeoutEx.Message}");
|
||
|
||
#if AGG
|
||
using (var e = GEvent.TackEvent("retry"))
|
||
{
|
||
e.AddContent("type", "config");
|
||
e.AddContent("duration_ms", elapsed.TotalMilliseconds);
|
||
e.AddContent("reason", $"timeout");
|
||
e.AddContent("skip", retryTimes >= 2);
|
||
e.AddContent("error", timeoutEx.Message);
|
||
}
|
||
#endif//AGG
|
||
}
|
||
catch (System.Security.Cryptography.CryptographicException cryptoEx)
|
||
{
|
||
if (stopwatch.IsRunning)
|
||
stopwatch.Stop();
|
||
var elapsed = stopwatch.Elapsed;
|
||
|
||
Debug.LogError($"Decryption failed: {cryptoEx.Message}");
|
||
|
||
#if AGG
|
||
using (var e = GEvent.TackEvent("retry"))
|
||
{
|
||
e.AddContent("type", "config");
|
||
e.AddContent("duration_ms", elapsed.TotalMilliseconds);
|
||
e.AddContent("reason", "cryptoEx");
|
||
e.AddContent("skip", retryTimes >= 2);
|
||
e.AddContent("error", cryptoEx.Message);
|
||
}
|
||
#endif//AGG
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
if (stopwatch.IsRunning)
|
||
stopwatch.Stop();
|
||
var elapsed = stopwatch.ElapsedMilliseconds;
|
||
|
||
var errorMessage = $"Unexpected error loading remote config: {exception.Message}";
|
||
if (exception.InnerException != null)
|
||
{
|
||
errorMessage += $" Inner: {exception.InnerException.Message}";
|
||
}
|
||
Debug.LogError(errorMessage);
|
||
|
||
#if AGG
|
||
using (var e = GEvent.TackEvent("retry"))
|
||
{
|
||
e.AddContent("type", "config");
|
||
e.AddContent("duration_ms", elapsed);
|
||
e.AddContent("reason", "unexpected_error");
|
||
e.AddContent("skip", retryTimes >= 2);
|
||
e.AddContent("error", errorMessage);
|
||
}
|
||
#endif//AGG
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
*/
|
||
|
||
/*
|
||
* public static async Task<JSONNode> GetRemoteConfig()
|
||
* {
|
||
* UnityEngine.Assertions.Assert.IsNotNull(RemoteConfigUrl, "Config is not inited");
|
||
* var request = UnityWebRequest.Get($"{RemoteConfigUrl}/{GConstant.V_Remote_Config_Path}");
|
||
* request.timeout = 5;
|
||
* await request.SendWebRequest();
|
||
*
|
||
* if (request.result != UnityWebRequest.Result.Success)
|
||
* {
|
||
* return null;
|
||
* }
|
||
*
|
||
* string remoteConfigStr = request.downloadHandler.text;
|
||
* remoteConfigStr = Decrypt(remoteConfigStr);
|
||
* return SimpleJSON.JSON.Parse(remoteConfigStr);
|
||
* }
|
||
*/
|
||
|
||
private static JSONNode GetStreamingAssetConfig()
|
||
{
|
||
var debugConfigPath = GConstant.V_Debug_Config_Path;
|
||
var text = BetterStreamingAssets.ReadAllText(debugConfigPath);
|
||
//如果第一个字符是#e,就返回false
|
||
if (!text.StartsWith("#"))
|
||
{
|
||
var debugConfig = SimpleJSON.JSON.Parse(text);
|
||
if (debugConfig.HasKey(GConstant.K_Static_Res_URL))
|
||
{
|
||
RemoteConfigUrl = debugConfig[GConstant.K_Static_Res_URL];
|
||
Debug.Log($"<color=yellow>Debug Static Res URL => {RemoteConfigUrl}</color>");
|
||
}
|
||
return debugConfig;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private static JSONNode GetPersistConfig()
|
||
{
|
||
var debugConfigPath = Path.Combine(Application.persistentDataPath, GConstant.V_Debug_Config_Path);
|
||
if (File.Exists(debugConfigPath))
|
||
{
|
||
var debugConfig = SimpleJSON.JSON.Parse(File.ReadAllText(debugConfigPath));
|
||
if (debugConfig.HasKey(GConstant.K_Static_Res_URL))
|
||
{
|
||
RemoteConfigUrl = debugConfig[GConstant.K_Static_Res_URL];
|
||
Debug.Log($"<color=yellow>Debug Static Res URL => {RemoteConfigUrl}</color>");
|
||
}
|
||
return debugConfig;
|
||
}
|
||
return null;
|
||
}
|
||
}
|