Commit a992169d authored by hex's avatar hex

fix download pic

parent e624f859
Pipeline #39153 failed
using UnityEngine; using System.Collections;
using System.Collections;
using DG.Tweening; using DG.Tweening;
using UnityEngine;
public class toolShift : MonoBehaviour { public class toolShift : MonoBehaviour
{
public GameObject ObjectMust = null; public GameObject ObjectMust = null;
public GameObject ObjectOption = null; public GameObject ObjectOption = null;
...@@ -42,31 +43,28 @@ public class toolShift : MonoBehaviour { ...@@ -42,31 +43,28 @@ public class toolShift : MonoBehaviour {
} }
public void shift() public void shift()
{
// 获取当前对象的本地坐标
Vector3 va = ObjectMust.transform.localPosition;
const float duration = 0.6f;
if (ObjectOption == null)
{ {
// 目标Y坐标,根据当前位置在 0 和 -100 之间切换 Vector3 va = ObjectMust.transform.localPosition;
float targetY = (va.y >= 0) ? -100f : 0f; const float duration = 0.6f;
// 使用 DOTween 的 DOLocalMoveY,因为它只改变Y轴,意图更明确且性能稍好 if (ObjectOption == null)
ObjectMust.transform.DOLocalMoveY(targetY, duration);
}
else
{
Vector3 vb = ObjectOption.transform.localPosition;
if (va.y > vb.y)
{ {
ObjectMust.transform.DOLocalMoveY(-100f, duration); float targetY = (va.y >= 0) ? -100f : 0f;
ObjectOption.transform.DOLocalMoveY(0f, duration); ObjectMust.transform.DOLocalMoveY(targetY, duration);
} }
else else
{ {
ObjectMust.transform.DOLocalMoveY(0f, duration); Vector3 vb = ObjectOption.transform.localPosition;
ObjectOption.transform.DOLocalMoveY(-100f, duration);
if (va.y > vb.y)
{
ObjectMust.transform.DOLocalMoveY(-100f, duration);
ObjectOption.transform.DOLocalMoveY(0f, duration);
}
else
{
ObjectMust.transform.DOLocalMoveY(0f, duration);
ObjectOption.transform.DOLocalMoveY(-100f, duration);
}
} }
} }
} }
}
...@@ -695,7 +695,7 @@ public class gameCard : OCGobject ...@@ -695,7 +695,7 @@ public class gameCard : OCGobject
//Program.I().audio.clip = Program.I().dididi; //Program.I().audio.clip = Program.I().dididi;
//Program.I().audio.Play(); //Program.I().audio.Play();
//deltaTimeCloseUp = 0; //deltaTimeCloseUp = 0;
DOTween.Kill(gameObject.transform); gameObject.transform.DOKill();
if (condition == gameCardCondition.floating_clickable) if (condition == gameCardCondition.floating_clickable)
{ {
flash_line_on(); flash_line_on();
...@@ -874,7 +874,7 @@ public class gameCard : OCGobject ...@@ -874,7 +874,7 @@ public class gameCard : OCGobject
// Let's use the calculated one unless we want a specific "exciting" ease. // Let's use the calculated one unless we want a specific "exciting" ease.
// The original code passed no ease, so we will not set one, letting DOTween use its default. // The original code passed no ease, so we will not set one, letting DOTween use its default.
} }
bool useArcPath = exciting || bool useArcPath = exciting ||
(Mathf.Abs(gameObject.transform.eulerAngles.x) < 10 && Vector3.Distance(pos, gameObject.transform.position) > 1f) || (Mathf.Abs(gameObject.transform.eulerAngles.x) < 10 && Vector3.Distance(pos, gameObject.transform.position) > 1f) ||
(accurate_position.x == pos.x && accurate_position.y < pos.y && accurate_position.z == pos.z); (accurate_position.x == pos.x && accurate_position.y < pos.y && accurate_position.z == pos.z);
...@@ -896,7 +896,7 @@ public class gameCard : OCGobject ...@@ -896,7 +896,7 @@ public class gameCard : OCGobject
float t = (float)i / 29f; float t = (float)i / 29f;
path[i] = from + (to - from) * t + new Vector3(0, 1.5f, 0) * Mathf.Sin(Mathf.PI * t); path[i] = from + (to - from) * t + new Vector3(0, 1.5f, 0) * Mathf.Sin(Mathf.PI * t);
} }
// Execute path and rotation tweens. // Execute path and rotation tweens.
gameObject.transform.DOPath(path, time).SetEase(easeType); gameObject.transform.DOPath(path, time).SetEase(easeType);
gameObject.transform.DORotate(rot, time).SetEase(easeType); gameObject.transform.DORotate(rot, time).SetEase(easeType);
...@@ -2299,7 +2299,7 @@ public class gameCard : OCGobject ...@@ -2299,7 +2299,7 @@ public class gameCard : OCGobject
) )
{ {
ES_lock(time_move + time_move + time_still); ES_lock(time_move + time_move + time_still);
gameObject.transform.DOKill(); gameObject.transform.DOKill();
// Create a sequence to chain the animations together // Create a sequence to chain the animations together
...@@ -2307,13 +2307,13 @@ public class gameCard : OCGobject ...@@ -2307,13 +2307,13 @@ public class gameCard : OCGobject
// 1. Move to the specified position and rotation // 1. Move to the specified position and rotation
confirmSequence.Append(gameObject.transform.DOMove(position, time_move)); confirmSequence.Append(gameObject.transform.DOMove(position, time_move));
confirmSequence.Join(gameObject.transform.DORotate(rotation, time_move)); confirmSequence.Join(gameObject.transform.DORotate(rotation, time_move));
// 2. Wait for the specified "still" time // 2. Wait for the specified "still" time
confirmSequence.AppendInterval(time_still); confirmSequence.AppendInterval(time_still);
// 3. Move back to the original accurate position and rotation // 3. Move back to the original accurate position and rotation
confirmSequence.Append(gameObject.transform.DOMove(accurate_position, time_move).SetEase(Ease.InQuad)); confirmSequence.Append(gameObject.transform.DOMove(accurate_position, time_move).SetEase(Ease.InQuad));
confirmSequence.Join(gameObject.transform.DORotate(accurate_rotation, time_move)); confirmSequence.Join(gameObject.transform.DORotate(accurate_rotation, time_move));
// 4. Set an OnUpdate for the entire sequence to keep decorations in place // 4. Set an OnUpdate for the entire sequence to keep decorations in place
confirmSequence.OnUpdate(RefreshFunction_decoration); confirmSequence.OnUpdate(RefreshFunction_decoration);
// We can assign the sequence to the transform to have it managed automatically // We can assign the sequence to the transform to have it managed automatically
...@@ -2324,7 +2324,7 @@ public class gameCard : OCGobject ...@@ -2324,7 +2324,7 @@ public class gameCard : OCGobject
{ {
ES_lock(time_move + time_move + time_still); ES_lock(time_move + time_move + time_still);
gameObject.transform.DOKill(); gameObject.transform.DOKill();
// Handle the screenFader component as before // Handle the screenFader component as before
var ttt = gameObject.AddComponent<screenFader>(); var ttt = gameObject.AddComponent<screenFader>();
ttt.from = gameObject.transform.position; ttt.from = gameObject.transform.position;
...@@ -2332,11 +2332,11 @@ public class gameCard : OCGobject ...@@ -2332,11 +2332,11 @@ public class gameCard : OCGobject
ttt.deltaTimeCloseUp = 0; ttt.deltaTimeCloseUp = 0;
MonoBehaviour.Destroy(ttt, time_move + time_still); MonoBehaviour.Destroy(ttt, time_move + time_still);
Sequence confirmSequence = DOTween.Sequence(); Sequence confirmSequence = DOTween.Sequence();
// 1. Rotate with a spring-like ease. Ease.OutElastic is a good equivalent for iTween's "spring". // 1. Rotate with a spring-like ease. Ease.OutElastic is a good equivalent for iTween's "spring".
// The movement is handled by the screenFader component. // The movement is handled by the screenFader component.
confirmSequence.Append(gameObject.transform.DORotate(rotation, time_move).SetEase(Ease.OutElastic)); confirmSequence.Append(gameObject.transform.DORotate(rotation, time_move).SetEase(Ease.OutElastic));
// 2. Hold // 2. Hold
confirmSequence.AppendInterval(time_still); confirmSequence.AppendInterval(time_still);
// 3. Return to original state. The original called confirm_step_3, which we replicate here. // 3. Return to original state. The original called confirm_step_3, which we replicate here.
...@@ -2351,7 +2351,7 @@ public class gameCard : OCGobject ...@@ -2351,7 +2351,7 @@ public class gameCard : OCGobject
ES_lock(time); ES_lock(time);
gameObject.transform.position = accurate_position; gameObject.transform.position = accurate_position;
gameObject.transform.eulerAngles = accurate_rotation; gameObject.transform.eulerAngles = accurate_rotation;
gameObject.transform.DOKill(); gameObject.transform.DOKill();
gameObject.transform.DOShakePosition(time, 1f) gameObject.transform.DOShakePosition(time, 1f)
...@@ -2377,7 +2377,7 @@ public class gameCard : OCGobject ...@@ -2377,7 +2377,7 @@ public class gameCard : OCGobject
{ {
return; return;
} }
show_off_disabled = disabled; show_off_disabled = disabled;
show_off_begin_time = Program.TimePassed(); show_off_begin_time = Program.TimePassed();
show_off_shokewave = summon; show_off_shokewave = summon;
......
...@@ -367,7 +367,7 @@ public class Program : MonoBehaviour ...@@ -367,7 +367,7 @@ public class Program : MonoBehaviour
InterString.initialize("config/translation.conf"); InterString.initialize("config/translation.conf");
// 显示一个简单的加载提示 // 显示一个简单的加载提示
PrintToChat(InterString.Get("正在加载本地数据...")); PrintToChat(InterString.Get("正在加载本地数据..."));
GameTextureManager.initialize(); // GameTextureManager.initialize();
Config.initialize("config/config.conf"); Config.initialize("config/config.conf");
// [新增] 封装文件加载逻辑,避免重复检查 // [新增] 封装文件加载逻辑,避免重复检查
......
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
...@@ -16,6 +17,51 @@ public enum GameTextureType ...@@ -16,6 +17,51 @@ public enum GameTextureType
public class GameTextureManager public class GameTextureManager
{ {
#region Main-Thread Bridge & Initialization
// ADDED: A structure to hold download request details.
internal struct DownloadRequest // 'internal' is good practice for helper structs
{
public string Url;
public string FilePath;
public PictureResource PicResource;
}
// ADDED: A thread-safe queue for download requests from the background thread.
private static readonly Queue<DownloadRequest> downloadRequestQueue = new Queue<DownloadRequest>();
// ADDED: Unity will automatically call this method once when the game loads,
// before any scene loads. This is the perfect place to set up our helper.
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void InitializeOnLoad()
{
// Create a hidden GameObject to host our runner.
GameObject runnerObject = new GameObject("GameTextureManagerRunner");
// Add our runner component to it.
runnerObject.AddComponent<GameTextureManagerRunner>();
// Ensure it persists across scene changes.
GameObject.DontDestroyOnLoad(runnerObject);
// The original initialize logic now goes here.
Initialize();
}
// ADDED: Helper methods for the runner to interact with the queue.
internal static bool HasDownloadRequests()
{
return downloadRequestQueue.Count > 0;
}
internal static DownloadRequest GetNextDownloadRequest()
{
lock(downloadRequestQueue)
{
return downloadRequestQueue.Dequeue();
}
}
#endregion
static bool bLock = false; static bool bLock = false;
static Stack<PictureResource> waitLoadStack = new Stack<PictureResource>(); static Stack<PictureResource> waitLoadStack = new Stack<PictureResource>();
...@@ -118,7 +164,7 @@ public class GameTextureManager ...@@ -118,7 +164,7 @@ public class GameTextureManager
} }
} }
private class PictureResource public class PictureResource
{ {
public GameTextureType type; public GameTextureType type;
public long code; public long code;
...@@ -199,10 +245,41 @@ public class GameTextureManager ...@@ -199,10 +245,41 @@ public class GameTextureManager
public static Texture2D rs = null; public static Texture2D rs = null;
public static Texture2D ts = null; public static Texture2D ts = null;
internal static IEnumerator DownloadAndProcessFile(DownloadRequest request)
{
yield return UnityFileDownloader.DownloadFileAsync(request.Url, request.FilePath, (success) =>
{
if (success)
{
Debug.Log("Download successful, processing card picture: " + request.PicResource.code);
LoadCardPicture(request.PicResource, request.FilePath);
}
else
{
Debug.LogWarning("Download failed for card: " + request.PicResource.code);
LoadCardPicture(request.PicResource, request.FilePath); // Let it handle the missing file
}
});
}
private static Thread main_thread;
// MODIFIED: In your original code, Program.Running was used. This is a more robust way.
private static bool IsRunning = true;
// Call this method from your main game logic on application quit to stop the thread.
public static void Shutdown()
{
IsRunning = false;
if(main_thread != null && main_thread.IsAlive)
{
main_thread.Join(100);
}
}
static void thread_run() static void thread_run()
{ {
while (Program.Running) while (IsRunning)
{ {
try try
{ {
...@@ -236,20 +313,20 @@ public class GameTextureManager ...@@ -236,20 +313,20 @@ public class GameTextureManager
switch (pic.type) switch (pic.type)
{ {
case GameTextureType.card_feature: case GameTextureType.card_feature:
{ {
ProcessingCardFeature(pic); ProcessingCardFeature(pic);
break; break;
} }
case GameTextureType.card_picture: case GameTextureType.card_picture:
{ {
ProcessingCardPicture(pic); ProcessingCardPicture(pic);
break; break;
} }
case GameTextureType.card_verticle_drawing: case GameTextureType.card_verticle_drawing:
{ {
ProcessingVerticleDrawing(pic); ProcessingVerticleDrawing(pic);
break; break;
} }
} }
} }
} }
...@@ -411,37 +488,6 @@ public class GameTextureManager ...@@ -411,37 +488,6 @@ public class GameTextureManager
private static void caculateK(PictureResource pic) private static void caculateK(PictureResource pic)
{ {
//int width = pic.hashed_data.GetLength(0);
//int height = pic.hashed_data.GetLength(1);
//int left = 0;
//int right = width;
//if (width > height)
//{
// left = (width - height) / 2;
// right = width - left;
//}
//int all = 0;
//for (int h = 0; h < height; h++)
//{
// for (int w = left; w < right; w++)
// {
// if (pic.hashed_data[w, h, 3] > 0.05f)
// {
// all += 1;
// }
// }
//}
//float result = ((float)all) / (((float)height) * ((float)(height)));
//pic.k = result + 0.4f;
//if (pic.k > 1)
//{
// pic.k = 1f;
//}
//if (pic.k < 0)
//{
// pic.k = 0.1f;
//}
int width = pic.hashed_data.GetLength(0); int width = pic.hashed_data.GetLength(0);
int height = pic.hashed_data.GetLength(1); int height = pic.hashed_data.GetLength(1);
int h = 0; int h = 0;
...@@ -848,16 +894,33 @@ public class GameTextureManager ...@@ -848,16 +894,33 @@ public class GameTextureManager
} }
if (!File.Exists(path) && pic.code != 0 && AutoPicDownload) if (!File.Exists(path) && pic.code != 0 && AutoPicDownload)
{ {
//YGOMobile (177x254) // //YGOMobile (177x254)
df.Download( // df.Download(
"http://cdn01.moestart.com/images/ygopro-images-zh-CN/" // "http://cdn01.moestart.com/images/ygopro-images-zh-CN/"
+ pic.code.ToString() // + pic.code.ToString()
+ ".jpg", // + ".jpg",
"picture/card/" + pic.code.ToString() + ".jpg" // "picture/card/" + pic.code.ToString() + ".jpg"
); // );
path = "picture/card/" + pic.code.ToString() + ".jpg"; // path = "picture/card/" + pic.code.ToString() + ".jpg";
string url = "https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/" + pic.code.ToString() + ".jpg";
// string url = "http://cdn01.moestart.com/images/ygopro-images-zh-CN/" + pic.code.ToString() + ".jpg";
string finalPath = "picture/card/" + pic.code.ToString() + ".jpg";
// Enqueue the request. The runner on the main thread will pick it up.
lock (downloadRequestQueue)
{
downloadRequestQueue.Enqueue(new DownloadRequest
{
Url = url,
FilePath = finalPath,
PicResource = pic
});
}
}
else
{
LoadCardPicture(pic, path);
} }
LoadCardPicture(pic, path);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -1028,7 +1091,7 @@ public class GameTextureManager ...@@ -1028,7 +1091,7 @@ public class GameTextureManager
public static UnityEngine.Color chainColor = UnityEngine.Color.white; public static UnityEngine.Color chainColor = UnityEngine.Color.white;
internal static void initialize() internal static void Initialize()
{ {
attack = UIHelper.getTexture2D("textures/attack.png"); //YGOMobile Paths attack = UIHelper.getTexture2D("textures/attack.png"); //YGOMobile Paths
myBack = UIHelper.getTexture2D("textures/cover.jpg"); //YGOMobile Paths myBack = UIHelper.getTexture2D("textures/cover.jpg"); //YGOMobile Paths
...@@ -1076,7 +1139,10 @@ public class GameTextureManager ...@@ -1076,7 +1139,10 @@ public class GameTextureManager
); //YGOMobile Paths ); //YGOMobile Paths
} }
catch (Exception) { } catch (Exception) { }
Thread main = new Thread(thread_run); if (main_thread == null)
main.Start(); {
main_thread = new Thread(thread_run);
main_thread.Start();
}
} }
} }
using System.Collections;
using UnityEngine;
/// <summary>
/// 这是一个 MonoBehaviour 帮助器,专为静态的 GameTextureManager 服务。
/// 它的职责是在主线程上执行任务,例如轮询下载队列和启动协程。
/// 这个类的实例由 GameTextureManager 通过 [RuntimeInitializeOnLoadMethod] 自动创建。
/// </summary>
public class GameTextureManagerRunner : MonoBehaviour
{
void Update()
{
// 在主线程的每一帧检查是否有待处理的下载请求
if (GameTextureManager.HasDownloadRequests())
{
// 从 GameTextureManager 获取一个请求
var request = GameTextureManager.GetNextDownloadRequest();
// 使用这个 MonoBehaviour 实例来启动下载协程
StartCoroutine(GameTextureManager.DownloadAndProcessFile(request));
}
}
}
fileFormatVersion: 2
guid: cb7d20dd5a7074bc089a6c75c87e34da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
...@@ -29,39 +29,40 @@ public static class GlobalCertificateManager ...@@ -29,39 +29,40 @@ public static class GlobalCertificateManager
SslPolicyErrors sslPolicyErrors SslPolicyErrors sslPolicyErrors
) )
{ {
// return true; // 都是从 cdn02 的官方资源下载,hook 掉不验证证书可以提高下载速度,但是有一定的安全风险
// Case 1: 证书本身没有问题,直接通过 return true;
if (sslPolicyErrors == SslPolicyErrors.None) // // Case 1: 证书本身没有问题,直接通过
{ // if (sslPolicyErrors == SslPolicyErrors.None)
return true; // {
} // return true;
// Case 2: 如果错误是 RemoteCertificateChainErrors, // }
// 这通常意味着证书链有问题,比如找不到吊销列表或者根证书不受信任。 // // Case 2: 如果错误是 RemoteCertificateChainErrors,
// 我们将尝试进行一次忽略吊销检查的自定义验证。 // // 这通常意味着证书链有问题,比如找不到吊销列表或者根证书不受信任。
if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0) // // 我们将尝试进行一次忽略吊销检查的自定义验证。
{ // if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0)
// 创建一个新的证书链对象 // {
X509Chain customChain = new X509Chain(); // // 创建一个新的证书链对象
// X509Chain customChain = new X509Chain();
// 设置自定义验证策略 // // 设置自定义验证策略
customChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; // <-- 核心:不检查证书吊销 // customChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; // <-- 核心:不检查证书吊销
customChain.ChainPolicy.VerificationFlags = // customChain.ChainPolicy.VerificationFlags =
X509VerificationFlags.AllowUnknownCertificateAuthority; // 可选:如果你的服务器是自签名证书,需要加上这句。如果服务器证书是由受信任的公共CA颁发的,可以去掉这句。 // X509VerificationFlags.AllowUnknownCertificateAuthority; // 可选:如果你的服务器是自签名证书,需要加上这句。如果服务器证书是由受信任的公共CA颁发的,可以去掉这句。
// 使用 X509Certificate2,因为它包含更完整的信息 // // 使用 X509Certificate2,因为它包含更完整的信息
X509Certificate2 cert2 = new X509Certificate2(certificate); // X509Certificate2 cert2 = new X509Certificate2(certificate);
// 使用自定义策略进行验证 // // 使用自定义策略进行验证
bool isChainValid = customChain.Build(cert2); // bool isChainValid = customChain.Build(cert2);
// 如果自定义验证构建成功,说明在忽略吊销检查的前提下,证书是可信的 // // 如果自定义验证构建成功,说明在忽略吊销检查的前提下,证书是可信的
if (isChainValid) // if (isChainValid)
{ // {
return true; // return true;
} // }
} // }
// Case 3: 对于其他错误(如名称不匹配 RemoteCertificateNameMismatch)或自定义验证失败, // // Case 3: 对于其他错误(如名称不匹配 RemoteCertificateNameMismatch)或自定义验证失败,
// 我们认为证书无效。 // // 我们认为证书无效。
Debug.LogErrorFormat("证书验证失败. SslPolicyErrors: {0}", sslPolicyErrors); // Debug.LogErrorFormat("证书验证失败. SslPolicyErrors: {0}", sslPolicyErrors);
return false; // return false;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment