com.beanbag.tiktokminigames 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/DefaultTemplate/backgroundlandscape.png +0 -0
  2. package/DefaultTemplate/backgroundlandscape.png.meta +159 -0
  3. package/DefaultTemplate/backgroundportrait.png +0 -0
  4. package/DefaultTemplate/backgroundportrait.png.meta +159 -0
  5. package/DefaultTemplate/game.js +151 -0
  6. package/DefaultTemplate/game.js.meta +7 -0
  7. package/DefaultTemplate/images/unity_logo.png +0 -0
  8. package/DefaultTemplate/images/unity_logo.png.meta +159 -0
  9. package/DefaultTemplate/images.meta +8 -0
  10. package/DefaultTemplate/plugin-config.js +23 -0
  11. package/DefaultTemplate/plugin-config.js.meta +7 -0
  12. package/DefaultTemplate/plugin.js +1 -0
  13. package/DefaultTemplate/plugin.js.meta +7 -0
  14. package/DefaultTemplate/unity-namespace.js +11 -0
  15. package/DefaultTemplate/unity-namespace.js.meta +7 -0
  16. package/DefaultTemplate/webgl-wasm-split.js +17 -0
  17. package/DefaultTemplate/webgl-wasm-split.js.meta +7 -0
  18. package/DefaultTemplate.meta +8 -0
  19. package/Editor/Extras/Integration/DouYinMiniGameSettings.cs +30 -0
  20. package/Editor/Extras/Integration/DouYinMiniGameSettings.cs.meta +11 -0
  21. package/Editor/Extras/Integration/DouYinMiniGameSettingsEditor.cs +354 -0
  22. package/Editor/Extras/Integration/DouYinMiniGameSettingsEditor.cs.meta +3 -0
  23. package/Editor/Extras/Integration/DouYinSubplatformInterface.cs +153 -0
  24. package/Editor/Extras/Integration/DouYinSubplatformInterface.cs.meta +3 -0
  25. package/Editor/Extras/Integration.meta +8 -0
  26. package/Editor/Extras/Providers/TTMiniGameSupportProvider.cs +148 -0
  27. package/Editor/Extras/Providers/TTMiniGameSupportProvider.cs.meta +3 -0
  28. package/Editor/Extras/Providers.meta +3 -0
  29. package/Editor/Extras/TTEditorSupportProviderRegister.cs +15 -0
  30. package/Editor/Extras/TTEditorSupportProviderRegister.cs.meta +3 -0
  31. package/Editor/Extras.meta +3 -0
  32. package/Editor/ttsdk_tools.dll +0 -0
  33. package/Editor/ttsdk_tools.dll.meta +33 -0
  34. package/Editor/ttsdk_tools.pdb +0 -0
  35. package/Editor/ttsdk_tools.pdb.meta +7 -0
  36. package/Editor.meta +8 -0
  37. package/LitJson/TTLitJson.dll +0 -0
  38. package/LitJson/TTLitJson.dll.meta +33 -0
  39. package/LitJson/TTLitJson.pdb +0 -0
  40. package/LitJson/TTLitJson.pdb.meta +7 -0
  41. package/LitJson.meta +8 -0
  42. package/TTSDK/ttsdk.dll +0 -0
  43. package/TTSDK/ttsdk.dll.meta +33 -0
  44. package/TTSDK/ttsdk.pdb +0 -0
  45. package/TTSDK/ttsdk.pdb.meta +7 -0
  46. package/TTSDK.meta +8 -0
  47. package/WebGL/AssetBundle/DownloadHandlerTTAssetBundle.cs +85 -0
  48. package/WebGL/AssetBundle/DownloadHandlerTTAssetBundle.cs.meta +3 -0
  49. package/WebGL/AssetBundle/TTAssetBundle.cs +72 -0
  50. package/WebGL/AssetBundle/TTAssetBundle.cs.meta +3 -0
  51. package/WebGL/AssetBundle/TTAssetBundleExtensions.cs +25 -0
  52. package/WebGL/AssetBundle/TTAssetBundleExtensions.cs.meta +3 -0
  53. package/WebGL/AssetBundle/TTAssetBundleProviders.cs.txt +1301 -0
  54. package/WebGL/AssetBundle/TTAssetBundleProviders.cs.txt.meta +3 -0
  55. package/WebGL/AssetBundle/TTAssetBundleRequest.cs +96 -0
  56. package/WebGL/AssetBundle/TTAssetBundleRequest.cs.meta +3 -0
  57. package/WebGL/AssetBundle.meta +8 -0
  58. package/WebGL/Compatibility/UnityCacheCompatibility.cs +49 -0
  59. package/WebGL/Compatibility/UnityCacheCompatibility.cs.meta +3 -0
  60. package/WebGL/Compatibility/UnityWebRequestCompatibility.cs +18 -0
  61. package/WebGL/Compatibility/UnityWebRequestCompatibility.cs.meta +3 -0
  62. package/WebGL/Compatibility.meta +3 -0
  63. package/WebGL/FileSystem/TTFileSystemManager.cs +460 -0
  64. package/WebGL/FileSystem/TTFileSystemManager.cs.meta +11 -0
  65. package/WebGL/FileSystem/TTFileSystemManagerDefault.cs +1039 -0
  66. package/WebGL/FileSystem/TTFileSystemManagerDefault.cs.meta +11 -0
  67. package/WebGL/FileSystem/TTFileSystemManagerWebGL.cs +1278 -0
  68. package/WebGL/FileSystem/TTFileSystemManagerWebGL.cs.meta +11 -0
  69. package/WebGL/FileSystem.meta +3 -0
  70. package/WebGL/Input/Input.cs +230 -0
  71. package/WebGL/Input/Input.cs.meta +3 -0
  72. package/WebGL/Input/TTPCInputHandler.cs +199 -0
  73. package/WebGL/Input/TTPCInputHandler.cs.meta +3 -0
  74. package/WebGL/Input.meta +3 -0
  75. package/WebGL/Network/TTUDPSocketHandler.cs +130 -0
  76. package/WebGL/Network/TTUDPSocketHandler.cs.meta +11 -0
  77. package/WebGL/Network.meta +3 -0
  78. package/WebGL/TTAssetBundle.jslib +33 -0
  79. package/WebGL/TTAssetBundle.jslib.meta +32 -0
  80. package/WebGL/TTCallbackHandler.cs +139 -0
  81. package/WebGL/TTCallbackHandler.cs.meta +3 -0
  82. package/WebGL/TTModel.cs +582 -0
  83. package/WebGL/TTModel.cs.meta +11 -0
  84. package/WebGL/TTSDK.jslib +592 -0
  85. package/WebGL/TTSDK.jslib.meta +32 -0
  86. package/WebGL/TTSDKType.cs +10 -0
  87. package/WebGL/TTSDKType.cs.meta +3 -0
  88. package/WebGL/TTStorageManager.cs +155 -0
  89. package/WebGL/TTStorageManager.cs.meta +11 -0
  90. package/WebGL/TTUNBridge.jslib +117 -0
  91. package/WebGL/TTUNBridge.jslib.meta +32 -0
  92. package/WebGL/TTVersionAttribute.cs +21 -0
  93. package/WebGL/TTVersionAttribute.cs.meta +11 -0
  94. package/WebGL/TTWebGL.asmdef +18 -0
  95. package/WebGL/TTWebGL.asmdef.meta +7 -0
  96. package/WebGL/TTWebGLInterface.cs +63 -0
  97. package/WebGL/TTWebGLInterface.cs.meta +11 -0
  98. package/WebGL.meta +8 -0
  99. package/package.json +13 -0
  100. package/package.json.meta +7 -0
@@ -0,0 +1,1301 @@
1
+ #if UNITY_2022_1_OR_NEWER
2
+ #define UNLOAD_BUNDLE_ASYNC
3
+ #endif
4
+
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.ComponentModel;
8
+ using System.IO;
9
+ using System.Threading;
10
+ using UnityEngine.Networking;
11
+ using UnityEngine.ResourceManagement.AsyncOperations;
12
+ using UnityEngine.ResourceManagement.Exceptions;
13
+ using UnityEngine.ResourceManagement.ResourceLocations;
14
+ using UnityEngine.ResourceManagement.Util;
15
+ using TTSDK;
16
+
17
+ namespace UnityEngine.ResourceManagement
18
+ {
19
+ internal class TTWebRequestQueueOperation
20
+ {
21
+ private bool m_Completed = false;
22
+ public UnityWebRequestAsyncOperation Result;
23
+ public Action<UnityWebRequestAsyncOperation> OnComplete;
24
+ public bool IsDone
25
+ {
26
+ get { return m_Completed || Result != null; }
27
+ }
28
+
29
+ internal UnityWebRequest m_WebRequest;
30
+
31
+ public UnityWebRequest WebRequest
32
+ {
33
+ get { return m_WebRequest; }
34
+ internal set { m_WebRequest = value; }
35
+ }
36
+
37
+ public TTWebRequestQueueOperation(UnityWebRequest request)
38
+ {
39
+ m_WebRequest = request;
40
+ }
41
+
42
+ internal void Complete(UnityWebRequestAsyncOperation asyncOp)
43
+ {
44
+ m_Completed = true;
45
+ Result = asyncOp;
46
+ OnComplete?.Invoke(Result);
47
+ }
48
+ }
49
+
50
+
51
+ internal static class WebRequestQueue
52
+ {
53
+ internal static int s_MaxRequest = 512;
54
+ internal static Queue<TTWebRequestQueueOperation> s_QueuedOperations = new Queue<TTWebRequestQueueOperation>();
55
+ internal static List<UnityWebRequestAsyncOperation> s_ActiveRequests = new List<UnityWebRequestAsyncOperation>();
56
+
57
+ public static void SetMaxConcurrentRequests(int maxRequests)
58
+ {
59
+ if (maxRequests < 1)
60
+ throw new ArgumentException("MaxRequests must be 1 or greater.", "maxRequests");
61
+ s_MaxRequest = maxRequests;
62
+ }
63
+
64
+ public static TTWebRequestQueueOperation QueueRequest(UnityWebRequest request)
65
+ {
66
+ TTWebRequestQueueOperation queueOperation = new TTWebRequestQueueOperation(request);
67
+ if (s_ActiveRequests.Count < s_MaxRequest)
68
+ BeginWebRequest(queueOperation);
69
+ else
70
+ s_QueuedOperations.Enqueue(queueOperation);
71
+
72
+ return queueOperation;
73
+ }
74
+
75
+ internal static void WaitForRequestToBeActive(TTWebRequestQueueOperation request, int millisecondsTimeout)
76
+ {
77
+ var completedRequests = new List<UnityWebRequestAsyncOperation>();
78
+ while (s_QueuedOperations.Contains(request))
79
+ {
80
+ completedRequests.Clear();
81
+ foreach (UnityWebRequestAsyncOperation webRequestAsyncOp in s_ActiveRequests)
82
+ {
83
+ if (TTUnityWebRequestUtilities.IsAssetBundleDownloaded(webRequestAsyncOp))
84
+ completedRequests.Add(webRequestAsyncOp);
85
+ }
86
+
87
+ foreach (UnityWebRequestAsyncOperation webRequestAsyncOp in completedRequests)
88
+ {
89
+ bool requestIsActive = s_QueuedOperations.Peek() == request;
90
+ webRequestAsyncOp.completed -= OnWebAsyncOpComplete;
91
+ OnWebAsyncOpComplete(webRequestAsyncOp);
92
+ if (requestIsActive)
93
+ return;
94
+ }
95
+
96
+ Thread.Sleep(millisecondsTimeout);
97
+ }
98
+ }
99
+
100
+ internal static void DequeueRequest(UnityWebRequestAsyncOperation operation)
101
+ {
102
+ operation.completed -= OnWebAsyncOpComplete;
103
+ OnWebAsyncOpComplete(operation);
104
+ }
105
+
106
+ private static void OnWebAsyncOpComplete(AsyncOperation operation)
107
+ {
108
+ OnWebAsyncOpComplete(operation as UnityWebRequestAsyncOperation);
109
+ }
110
+
111
+ private static void OnWebAsyncOpComplete(UnityWebRequestAsyncOperation operation)
112
+ {
113
+ if (s_ActiveRequests.Remove(operation) && s_QueuedOperations.Count > 0)
114
+ {
115
+ var nextQueuedOperation = s_QueuedOperations.Dequeue();
116
+ BeginWebRequest(nextQueuedOperation);
117
+ }
118
+ }
119
+
120
+ static void BeginWebRequest(TTWebRequestQueueOperation queueOperation)
121
+ {
122
+ var request = queueOperation.m_WebRequest;
123
+ UnityWebRequestAsyncOperation webRequestAsyncOp = null;
124
+ try
125
+ {
126
+ webRequestAsyncOp = request.SendWebRequest();
127
+ if (webRequestAsyncOp != null)
128
+ {
129
+ s_ActiveRequests.Add(webRequestAsyncOp);
130
+
131
+ if (webRequestAsyncOp.isDone)
132
+ OnWebAsyncOpComplete(webRequestAsyncOp);
133
+ else
134
+ webRequestAsyncOp.completed += OnWebAsyncOpComplete;
135
+ }
136
+ else
137
+ {
138
+ OnWebAsyncOpComplete(null);
139
+ }
140
+ }
141
+ catch (Exception e)
142
+ {
143
+ Debug.LogError(e.Message);
144
+ }
145
+
146
+ queueOperation.Complete(webRequestAsyncOp);
147
+ }
148
+ }
149
+ }
150
+
151
+ namespace UnityEngine.ResourceManagement.Util
152
+ {
153
+ [Flags]
154
+ internal enum BundleSource
155
+ {
156
+ None = 0,
157
+ Local = 1,
158
+ Cache = 2,
159
+ Download = 4,
160
+ }
161
+ }
162
+
163
+ namespace UnityEngine.ResourceManagement.ResourceProviders
164
+ {
165
+
166
+ [DisplayName("Assets from TTBundles Provider")]
167
+ public class TTBundledAssetProvider : ResourceProviderBase
168
+ {
169
+ internal class InternalOp
170
+ {
171
+ AssetBundle m_AssetBundle;
172
+ AssetBundleRequest m_PreloadRequest;
173
+ AssetBundleRequest m_RequestOperation;
174
+ object m_Result;
175
+ ProvideHandle m_ProvideHandle;
176
+ string subObjectName = null;
177
+
178
+ internal static T LoadBundleFromDependecies<T>(IList<object> results) where T : class, IAssetBundleResource
179
+ {
180
+ if (results == null || results.Count == 0)
181
+ return default(T);
182
+
183
+ IAssetBundleResource bundle = null;
184
+ bool firstBundleWrapper = true;
185
+ for (int i = 0; i < results.Count; i++)
186
+ {
187
+ var abWrapper = results[i] as IAssetBundleResource;
188
+ if (abWrapper != null)
189
+ {
190
+ //only use the first asset bundle, even if it is invalid
191
+ abWrapper.GetAssetBundle();
192
+ if (firstBundleWrapper)
193
+ bundle = abWrapper;
194
+ firstBundleWrapper = false;
195
+ }
196
+ }
197
+
198
+ return bundle as T;
199
+ }
200
+
201
+ public void Start(ProvideHandle provideHandle)
202
+ {
203
+ provideHandle.SetProgressCallback(ProgressCallback);
204
+ provideHandle.SetWaitForCompletionCallback(WaitForCompletionHandler);
205
+ subObjectName = null;
206
+ m_ProvideHandle = provideHandle;
207
+ m_RequestOperation = null;
208
+ List<object> deps = new List<object>();
209
+ m_ProvideHandle.GetDependencies(deps);
210
+ var bundleResource = LoadBundleFromDependecies<IAssetBundleResource>(deps);
211
+ if (bundleResource == null)
212
+ {
213
+ m_ProvideHandle.Complete<AssetBundle>(null, false, new Exception("Unable to load dependent bundle from location " + m_ProvideHandle.Location));
214
+ }
215
+ else
216
+ {
217
+ m_AssetBundle = bundleResource.GetAssetBundle();
218
+ if (m_AssetBundle == null)
219
+ {
220
+ m_ProvideHandle.Complete<AssetBundle>(null, false, new Exception("Unable to load dependent bundle from location " + m_ProvideHandle.Location));
221
+ return;
222
+ }
223
+
224
+ var assetBundleResource = bundleResource as TTAssetBundleResource;
225
+ if (assetBundleResource != null)
226
+ m_PreloadRequest = assetBundleResource.GetAssetPreloadRequest();
227
+ if (m_PreloadRequest == null || m_PreloadRequest.isDone)
228
+ BeginAssetLoad();
229
+ else
230
+ m_PreloadRequest.completed += operation => BeginAssetLoad();
231
+ }
232
+ }
233
+
234
+ private void BeginAssetLoad()
235
+ {
236
+ if (m_AssetBundle == null)
237
+ {
238
+ m_ProvideHandle.Complete<AssetBundle>(null, false, new Exception("Unable to load dependent bundle from location " + m_ProvideHandle.Location));
239
+ }
240
+ else
241
+ {
242
+ var assetPath = m_ProvideHandle.ResourceManager.TransformInternalId(m_ProvideHandle.Location);
243
+ if (m_ProvideHandle.Type.IsArray)
244
+ {
245
+ #if !UNITY_2021_1_OR_NEWER
246
+ if (AsyncOperationHandle.IsWaitingForCompletion)
247
+ {
248
+ GetArrayResult(m_AssetBundle.LoadAssetWithSubAssets(assetPath, m_ProvideHandle.Type.GetElementType()));
249
+ CompleteOperation();
250
+ }
251
+ else
252
+ #endif
253
+ m_RequestOperation = m_AssetBundle.LoadAssetWithSubAssetsAsync(assetPath, m_ProvideHandle.Type.GetElementType());
254
+ }
255
+ else if (m_ProvideHandle.Type.IsGenericType && typeof(IList<>) == m_ProvideHandle.Type.GetGenericTypeDefinition())
256
+ {
257
+ #if !UNITY_2021_1_OR_NEWER
258
+ if (AsyncOperationHandle.IsWaitingForCompletion)
259
+ {
260
+ GetListResult(m_AssetBundle.LoadAssetWithSubAssets(assetPath, m_ProvideHandle.Type.GetGenericArguments()[0]));
261
+ CompleteOperation();
262
+ }
263
+ else
264
+ #endif
265
+ m_RequestOperation = m_AssetBundle.LoadAssetWithSubAssetsAsync(assetPath, m_ProvideHandle.Type.GetGenericArguments()[0]);
266
+ }
267
+ else
268
+ {
269
+ if (ExtractKeyAndSubKey(assetPath, out string mainPath, out string subKey))
270
+ {
271
+ subObjectName = subKey;
272
+ #if !UNITY_2021_1_OR_NEWER
273
+ if (AsyncOperationHandle.IsWaitingForCompletion)
274
+ {
275
+ GetAssetSubObjectResult(m_AssetBundle.LoadAssetWithSubAssets(mainPath, m_ProvideHandle.Type));
276
+ CompleteOperation();
277
+ }
278
+ else
279
+ #endif
280
+ m_RequestOperation = m_AssetBundle.LoadAssetWithSubAssetsAsync(mainPath, m_ProvideHandle.Type);
281
+ }
282
+ else
283
+ {
284
+ #if !UNITY_2021_1_OR_NEWER
285
+ if (AsyncOperationHandle.IsWaitingForCompletion)
286
+ {
287
+ GetAssetResult(m_AssetBundle.LoadAsset(assetPath, m_ProvideHandle.Type));
288
+ CompleteOperation();
289
+ }
290
+ else
291
+ #endif
292
+ m_RequestOperation = m_AssetBundle.LoadAssetAsync(assetPath, m_ProvideHandle.Type);
293
+ }
294
+ }
295
+
296
+ if (m_RequestOperation != null)
297
+ {
298
+ if (m_RequestOperation.isDone)
299
+ ActionComplete(m_RequestOperation);
300
+ else
301
+ {
302
+ #if ENABLE_ADDRESSABLE_PROFILER
303
+ if (UnityEngine.Profiling.Profiler.enabled && m_ProvideHandle.IsValid)
304
+ Profiling.ProfilerRuntime.AddAssetOperation(m_ProvideHandle, Profiling.ContentStatus.Loading);
305
+ #endif
306
+ m_RequestOperation.completed += ActionComplete;
307
+ }
308
+ }
309
+ }
310
+ }
311
+
312
+ private bool WaitForCompletionHandler()
313
+ {
314
+ if (m_PreloadRequest != null && !m_PreloadRequest.isDone)
315
+ return m_PreloadRequest.asset == null;
316
+ if (m_Result != null)
317
+ return true;
318
+ if (m_RequestOperation == null)
319
+ return false;
320
+ if (m_RequestOperation.isDone)
321
+ return true;
322
+ return m_RequestOperation.asset != null;
323
+ }
324
+
325
+ private void ActionComplete(AsyncOperation obj)
326
+ {
327
+ if (m_RequestOperation != null)
328
+ {
329
+ if (m_ProvideHandle.Type.IsArray)
330
+ GetArrayResult(m_RequestOperation.allAssets);
331
+ else if (m_ProvideHandle.Type.IsGenericType && typeof(IList<>) == m_ProvideHandle.Type.GetGenericTypeDefinition())
332
+ GetListResult(m_RequestOperation.allAssets);
333
+ else if (string.IsNullOrEmpty(subObjectName))
334
+ GetAssetResult(m_RequestOperation.asset);
335
+ else
336
+ GetAssetSubObjectResult(m_RequestOperation.allAssets);
337
+ }
338
+
339
+ CompleteOperation();
340
+ }
341
+
342
+ private void GetArrayResult(Object[] allAssets)
343
+ {
344
+ m_Result = ResourceManagerConfig.CreateArrayResult(m_ProvideHandle.Type, allAssets);
345
+ }
346
+
347
+ private void GetListResult(Object[] allAssets)
348
+ {
349
+ m_Result = ResourceManagerConfig.CreateListResult(m_ProvideHandle.Type, allAssets);
350
+ }
351
+
352
+ private void GetAssetResult(Object asset)
353
+ {
354
+ m_Result = (asset != null && m_ProvideHandle.Type.IsAssignableFrom(asset.GetType())) ? asset : null;
355
+ }
356
+
357
+ private void GetAssetSubObjectResult(Object[] allAssets)
358
+ {
359
+ foreach (var o in allAssets)
360
+ {
361
+ if (o.name == subObjectName)
362
+ {
363
+ if (m_ProvideHandle.Type.IsAssignableFrom(o.GetType()))
364
+ {
365
+ m_Result = o;
366
+ break;
367
+ }
368
+ }
369
+ }
370
+ }
371
+
372
+ void CompleteOperation()
373
+ {
374
+ #if ENABLE_ADDRESSABLE_PROFILER
375
+ if (UnityEngine.Profiling.Profiler.enabled && m_Result != null && m_ProvideHandle.IsValid)
376
+ Profiling.ProfilerRuntime.AddAssetOperation(m_ProvideHandle, Profiling.ContentStatus.Active);
377
+ #endif
378
+
379
+ Exception e = m_Result == null
380
+ ? new Exception($"Unable to load asset of type {m_ProvideHandle.Type} from location {m_ProvideHandle.Location}.")
381
+ : null;
382
+ m_ProvideHandle.Complete(m_Result, m_Result != null, e);
383
+ }
384
+
385
+ public float ProgressCallback()
386
+ {
387
+ return m_RequestOperation != null ? m_RequestOperation.progress : 0.0f;
388
+ }
389
+
390
+ /// <summary>
391
+ /// Extracts main and subobject keys if properly formatted
392
+ /// </summary>
393
+ /// <param name="keyObj">The key as an object.</param>
394
+ /// <param name="mainKey">The key of the main asset. This will be set to null if a sub key is not found.</param>
395
+ /// <param name="subKey">The key of the sub object. This will be set to null if not found.</param>
396
+ /// <returns></returns>
397
+ internal static bool ExtractKeyAndSubKey(object keyObj, out string mainKey, out string subKey)
398
+ {
399
+ var key = keyObj as string;
400
+ if (key != null)
401
+ {
402
+ var i = key.IndexOf('[');
403
+ if (i > 0)
404
+ {
405
+ var j = key.LastIndexOf(']');
406
+ if (j > i)
407
+ {
408
+ mainKey = key.Substring(0, i);
409
+ subKey = key.Substring(i + 1, j - (i + 1));
410
+ return true;
411
+ }
412
+ }
413
+ }
414
+ mainKey = null;
415
+ subKey = null;
416
+ return false;
417
+ }
418
+ }
419
+
420
+ public override void Provide(ProvideHandle provideHandle)
421
+ {
422
+ new InternalOp().Start(provideHandle);
423
+ }
424
+ }
425
+
426
+ public class TTAssetBundleResource : IAssetBundleResource, IUpdateReceiver
427
+ {
428
+ public enum LoadType
429
+ {
430
+ None,
431
+ Local,
432
+ Web
433
+ }
434
+
435
+ AssetBundle m_AssetBundle;
436
+ DownloadHandlerTTAssetBundle m_downloadHandler;
437
+ AsyncOperation m_RequestOperation;
438
+ internal TTWebRequestQueueOperation m_WebRequestQueueOperation;
439
+ internal ProvideHandle m_ProvideHandle;
440
+ internal AssetBundleRequestOptions m_Options;
441
+
442
+ [NonSerialized]
443
+ bool m_RequestCompletedCallbackCalled = false;
444
+
445
+ int m_Retries;
446
+ BundleSource m_Source = BundleSource.None;
447
+ long m_BytesToDownload;
448
+ long m_DownloadedBytes;
449
+ bool m_Completed = false;
450
+ #if UNLOAD_BUNDLE_ASYNC
451
+ AssetBundleUnloadOperation m_UnloadOperation;
452
+ #endif
453
+ const int k_WaitForWebRequestMainThreadSleep = 1;
454
+ string m_TransformedInternalId;
455
+ AssetBundleRequest m_PreloadRequest;
456
+ bool m_PreloadCompleted = false;
457
+ ulong m_LastDownloadedByteCount = 0;
458
+ float m_TimeoutTimer = 0;
459
+ int m_TimeoutOverFrames = 0;
460
+
461
+ private bool HasTimedOut => m_TimeoutTimer >= m_Options.Timeout && m_TimeoutOverFrames > 5;
462
+
463
+ internal long BytesToDownload
464
+ {
465
+ get
466
+ {
467
+ if (m_BytesToDownload == -1)
468
+ {
469
+ if (m_Options != null)
470
+ m_BytesToDownload = m_Options.ComputeSize(m_ProvideHandle.Location, m_ProvideHandle.ResourceManager);
471
+ else
472
+ m_BytesToDownload = 0;
473
+ }
474
+
475
+ return m_BytesToDownload;
476
+ }
477
+ }
478
+
479
+ internal UnityWebRequest CreateWebRequest(IResourceLocation loc)
480
+ {
481
+ var url = m_ProvideHandle.ResourceManager.TransformInternalId(loc);
482
+ return CreateWebRequest(url);
483
+ }
484
+
485
+ internal UnityWebRequest CreateWebRequest(string url)
486
+ {
487
+ string sanitizedUrl = Uri.UnescapeDataString(url);
488
+
489
+ #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
490
+ Uri uri = new Uri(sanitizedUrl.Replace(" ", "%20"));
491
+ #else
492
+ Uri uri = new Uri(Uri.EscapeUriString(sanitizedUrl));
493
+ #endif
494
+
495
+ if (m_Options == null)
496
+ {
497
+ m_Source = BundleSource.Download;
498
+ #if ENABLE_ADDRESSABLE_PROFILER
499
+ AddBundleToProfiler(Profiling.ContentStatus.Downloading, m_Source);
500
+ #endif
501
+ return TTAssetBundle.GetAssetBundle(url);
502
+ }
503
+
504
+ UnityWebRequest webRequest;
505
+ if (!string.IsNullOrEmpty(m_Options.Hash))
506
+ {
507
+ CachedAssetBundle cachedBundle = new CachedAssetBundle(m_Options.BundleName, Hash128.Parse(m_Options.Hash));
508
+ #if ENABLE_CACHING
509
+ bool cached = Caching.IsVersionCached(cachedBundle);
510
+ m_Source = cached ? BundleSource.Cache : BundleSource.Download;
511
+ if (m_Options.UseCrcForCachedBundle || m_Source == BundleSource.Download)
512
+ webRequest = UnityWebRequestAssetBundle.GetAssetBundle(uri, cachedBundle, m_Options.Crc);
513
+ else
514
+ webRequest = UnityWebRequestAssetBundle.GetAssetBundle(uri, cachedBundle);
515
+ #else
516
+ webRequest = UnityWebRequestAssetBundle.GetAssetBundle(uri, cachedBundle, m_Options.Crc);
517
+ #endif
518
+ }
519
+ else
520
+ {
521
+ m_Source = BundleSource.Download;
522
+ webRequest = TTAssetBundle.GetAssetBundle(url, m_Options.Crc);
523
+ }
524
+
525
+ if (m_Options.RedirectLimit > 0)
526
+ webRequest.redirectLimit = m_Options.RedirectLimit;
527
+ if (m_ProvideHandle.ResourceManager.CertificateHandlerInstance != null)
528
+ {
529
+ webRequest.certificateHandler = m_ProvideHandle.ResourceManager.CertificateHandlerInstance;
530
+ webRequest.disposeCertificateHandlerOnDispose = false;
531
+ }
532
+
533
+ m_ProvideHandle.ResourceManager.WebRequestOverride?.Invoke(webRequest);
534
+ return webRequest;
535
+ }
536
+
537
+ public AssetBundleRequest GetAssetPreloadRequest()
538
+ {
539
+ if (m_PreloadCompleted || GetAssetBundle() == null)
540
+ return null;
541
+
542
+ if (m_Options.AssetLoadMode == AssetLoadMode.AllPackedAssetsAndDependencies)
543
+ {
544
+ #if !UNITY_2021_1_OR_NEWER
545
+ if (AsyncOperationHandle.IsWaitingForCompletion)
546
+ {
547
+ m_AssetBundle.LoadAllAssets();
548
+ m_PreloadCompleted = true;
549
+ return null;
550
+ }
551
+ #endif
552
+ if (m_PreloadRequest == null)
553
+ {
554
+ m_PreloadRequest = m_AssetBundle.LoadAllAssetsAsync();
555
+ m_PreloadRequest.completed += operation => m_PreloadCompleted = true;
556
+ }
557
+
558
+ return m_PreloadRequest;
559
+ }
560
+
561
+ return null;
562
+ }
563
+
564
+ float PercentComplete()
565
+ {
566
+ return m_RequestOperation != null ? m_RequestOperation.progress : 0.0f;
567
+ }
568
+
569
+ DownloadStatus GetDownloadStatus()
570
+ {
571
+ if (m_Options == null)
572
+ return default;
573
+ var status = new DownloadStatus() {TotalBytes = BytesToDownload, IsDone = PercentComplete() >= 1f};
574
+ if (BytesToDownload > 0)
575
+ {
576
+ if (m_WebRequestQueueOperation != null && string.IsNullOrEmpty(m_WebRequestQueueOperation.m_WebRequest.error))
577
+ m_DownloadedBytes = (long)(m_WebRequestQueueOperation.m_WebRequest.downloadedBytes);
578
+ else if (m_RequestOperation != null && m_RequestOperation is UnityWebRequestAsyncOperation operation && string.IsNullOrEmpty(operation.webRequest.error))
579
+ m_DownloadedBytes = (long)operation.webRequest.downloadedBytes;
580
+ }
581
+
582
+ status.DownloadedBytes = m_DownloadedBytes;
583
+ return status;
584
+ }
585
+
586
+ public AssetBundle GetAssetBundle()
587
+ {
588
+ if (m_AssetBundle == null)
589
+ {
590
+ if (m_downloadHandler != null)
591
+ {
592
+ m_AssetBundle = m_downloadHandler.assetBundle;
593
+ m_downloadHandler.Dispose();
594
+ m_downloadHandler = null;
595
+ } else if (m_RequestOperation is TTAssetBundleRequest r)
596
+ {
597
+ m_AssetBundle = r.assetBundle;
598
+ }
599
+ }
600
+
601
+ return m_AssetBundle;
602
+ }
603
+
604
+ #if ENABLE_ADDRESSABLE_PROFILER
605
+ private void AddBundleToProfiler(Profiling.ContentStatus status, BundleSource source)
606
+ {
607
+ if (!Profiler.enabled)
608
+ return;
609
+
610
+ if (status == Profiling.ContentStatus.Active && m_AssetBundle == null)
611
+ Profiling.ProfilerRuntime.BundleReleased(m_Options.BundleName);
612
+ else
613
+ Profiling.ProfilerRuntime.AddBundleOperation(m_ProvideHandle, m_Options, status, source);
614
+ }
615
+
616
+ private void RemoveBundleFromProfiler()
617
+ {
618
+ if (m_Options == null)
619
+ return;
620
+ Profiling.ProfilerRuntime.BundleReleased(m_Options.BundleName);
621
+ }
622
+
623
+ #endif
624
+
625
+ #if UNLOAD_BUNDLE_ASYNC
626
+ void OnUnloadOperationComplete(AsyncOperation op)
627
+ {
628
+ m_UnloadOperation = null;
629
+ BeginOperation();
630
+ }
631
+
632
+ #endif
633
+
634
+ #if UNLOAD_BUNDLE_ASYNC
635
+ public void Start(ProvideHandle provideHandle, AssetBundleUnloadOperation unloadOp)
636
+ #else
637
+ public void Start(ProvideHandle provideHandle)
638
+ #endif
639
+ {
640
+ m_Retries = 0;
641
+ m_AssetBundle = null;
642
+ m_RequestOperation = null;
643
+ m_ProvideHandle = provideHandle;
644
+ m_Options = m_ProvideHandle.Location.Data as AssetBundleRequestOptions;
645
+ m_BytesToDownload = -1;
646
+ m_ProvideHandle.SetProgressCallback(PercentComplete);
647
+ m_ProvideHandle.SetDownloadProgressCallbacks(GetDownloadStatus);
648
+ m_ProvideHandle.SetWaitForCompletionCallback(WaitForCompletionHandler);
649
+ #if UNLOAD_BUNDLE_ASYNC
650
+ m_UnloadOperation = unloadOp;
651
+ if (m_UnloadOperation != null && !m_UnloadOperation.isDone)
652
+ m_UnloadOperation.completed += OnUnloadOperationComplete;
653
+ else
654
+ #endif
655
+ BeginOperation();
656
+ }
657
+
658
+ private bool WaitForCompletionHandler()
659
+ {
660
+ #if UNLOAD_BUNDLE_ASYNC
661
+ if (m_UnloadOperation != null && !m_UnloadOperation.isDone)
662
+ {
663
+ m_UnloadOperation.completed -= OnUnloadOperationComplete;
664
+ m_UnloadOperation.WaitForCompletion();
665
+ m_UnloadOperation = null;
666
+ BeginOperation();
667
+ }
668
+ #endif
669
+
670
+ if (m_RequestOperation == null)
671
+ {
672
+ if (m_WebRequestQueueOperation == null)
673
+ return false;
674
+ else
675
+ WebRequestQueue.WaitForRequestToBeActive(m_WebRequestQueueOperation, k_WaitForWebRequestMainThreadSleep);
676
+ }
677
+
678
+ if (m_RequestOperation is UnityWebRequestAsyncOperation op)
679
+ {
680
+ while (!TTUnityWebRequestUtilities.IsAssetBundleDownloaded(op))
681
+ Thread.Sleep(k_WaitForWebRequestMainThreadSleep);
682
+ #if ENABLE_ASYNC_ASSETBUNDLE_UWR
683
+ if (m_Source == BundleSource.Cache)
684
+ {
685
+ var downloadHandler = (DownloadHandlerTTAssetBundle)op?.webRequest?.downloadHandler;
686
+ if (downloadHandler.autoLoadAssetBundle)
687
+ m_AssetBundle = downloadHandler.assetBundle;
688
+ }
689
+ #endif
690
+ WebRequestQueue.DequeueRequest(op);
691
+
692
+ if (!m_RequestCompletedCallbackCalled)
693
+ {
694
+ m_RequestOperation.completed -= WebRequestOperationCompleted;
695
+ WebRequestOperationCompleted(m_RequestOperation);
696
+ }
697
+ }
698
+
699
+ if (!m_Completed && m_Source == BundleSource.Local)
700
+ {
701
+ if (!m_RequestCompletedCallbackCalled)
702
+ {
703
+ m_RequestOperation.completed -= LocalRequestOperationCompleted;
704
+ LocalRequestOperationCompleted(m_RequestOperation);
705
+ }
706
+ }
707
+
708
+ if (!m_Completed && m_RequestOperation.isDone)
709
+ {
710
+ m_ProvideHandle.Complete(this, m_AssetBundle != null, null);
711
+ m_Completed = true;
712
+ }
713
+
714
+ return m_Completed;
715
+ }
716
+
717
+ void AddCallbackInvokeIfDone(AsyncOperation operation, Action<AsyncOperation> callback)
718
+ {
719
+ if (operation.isDone)
720
+ callback(operation);
721
+ else
722
+ operation.completed += callback;
723
+ }
724
+
725
+ public static void GetLoadInfo(ProvideHandle handle, out LoadType loadType, out string path)
726
+ {
727
+ GetLoadInfo(handle.Location, handle.ResourceManager, out loadType, out path);
728
+ }
729
+
730
+ internal static void GetLoadInfo(IResourceLocation location, ResourceManager resourceManager, out LoadType loadType, out string path)
731
+ {
732
+ var options = location?.Data as AssetBundleRequestOptions;
733
+ if (options == null)
734
+ {
735
+ loadType = LoadType.None;
736
+ path = null;
737
+ return;
738
+ }
739
+
740
+ path = resourceManager.TransformInternalId(location);
741
+ if (Application.platform == RuntimePlatform.Android && path.StartsWith("jar:", StringComparison.Ordinal))
742
+ loadType = options.UseUnityWebRequestForLocalBundles ? LoadType.Web : LoadType.Local;
743
+ else if (ResourceManagerConfig.ShouldPathUseWebRequest(path))
744
+ loadType = LoadType.Web;
745
+ else if (options.UseUnityWebRequestForLocalBundles)
746
+ {
747
+ path = "file:///" + Path.GetFullPath(path);
748
+ loadType = LoadType.Web;
749
+ }
750
+ else
751
+ loadType = LoadType.Local;
752
+
753
+ if (loadType == LoadType.Web)
754
+ path = path.Replace('\\', '/');
755
+ }
756
+
757
+ private void BeginOperation()
758
+ {
759
+ m_DownloadedBytes = 0;
760
+ m_RequestCompletedCallbackCalled = false;
761
+ GetLoadInfo(m_ProvideHandle, out LoadType loadType, out m_TransformedInternalId);
762
+
763
+ if (loadType == LoadType.Local)
764
+ {
765
+ LoadLocalBundle();
766
+ return;
767
+ }
768
+
769
+ if (loadType == LoadType.Web)
770
+ {
771
+ m_WebRequestQueueOperation = EnqueueWebRequest(m_TransformedInternalId);
772
+ AddBeginWebRequestHandler(m_WebRequestQueueOperation);
773
+ return;
774
+ }
775
+
776
+ m_Source = BundleSource.None;
777
+ m_RequestOperation = null;
778
+ m_ProvideHandle.Complete<TTAssetBundleResource>(null, false,
779
+ new RemoteProviderException(string.Format("Invalid path in AssetBundleProvider: '{0}'.", m_TransformedInternalId), m_ProvideHandle.Location));
780
+ m_Completed = true;
781
+ }
782
+
783
+ private void LoadLocalBundle()
784
+ {
785
+ m_Source = BundleSource.Local;
786
+ #if !UNITY_2021_1_OR_NEWER
787
+ if (AsyncOperationHandle.IsWaitingForCompletion)
788
+ CompleteBundleLoad(AssetBundle.LoadFromFile(m_TransformedInternalId, m_Options == null ? 0 : m_Options.Crc));
789
+ else
790
+ #endif
791
+ {
792
+ m_RequestOperation = AssetBundle.LoadFromFileAsync(m_TransformedInternalId, m_Options == null ? 0 : m_Options.Crc);
793
+ #if ENABLE_ADDRESSABLE_PROFILER
794
+ AddBundleToProfiler(Profiling.ContentStatus.Loading, m_Source);
795
+ #endif
796
+ AddCallbackInvokeIfDone(m_RequestOperation, LocalRequestOperationCompleted);
797
+ }
798
+ }
799
+
800
+ internal TTWebRequestQueueOperation EnqueueWebRequest(string internalId)
801
+ {
802
+ var req = CreateWebRequest(internalId);
803
+ #if ENABLE_ASYNC_ASSETBUNDLE_UWR
804
+ ((DownloadHandlerAssetBundle)req.downloadHandler).autoLoadAssetBundle = true;
805
+ #endif
806
+ req.disposeDownloadHandlerOnDispose = false;
807
+
808
+ return WebRequestQueue.QueueRequest(req);
809
+ }
810
+
811
+ internal void AddBeginWebRequestHandler(TTWebRequestQueueOperation webRequestQueueOperation)
812
+ {
813
+ if (webRequestQueueOperation.IsDone)
814
+ {
815
+ BeginWebRequestOperation(webRequestQueueOperation.Result);
816
+ }
817
+ else
818
+ {
819
+ #if ENABLE_ADDRESSABLE_PROFILER
820
+ AddBundleToProfiler(Profiling.ContentStatus.Queue, m_Source);
821
+ #endif
822
+ webRequestQueueOperation.OnComplete += asyncOp => BeginWebRequestOperation(asyncOp);
823
+ }
824
+ }
825
+
826
+ private void BeginWebRequestOperation(AsyncOperation asyncOp)
827
+ {
828
+ m_TimeoutTimer = 0;
829
+ m_TimeoutOverFrames = 0;
830
+ m_LastDownloadedByteCount = 0;
831
+ m_RequestOperation = asyncOp;
832
+ if (m_RequestOperation == null || m_RequestOperation.isDone)
833
+ WebRequestOperationCompleted(m_RequestOperation);
834
+ else
835
+ {
836
+ if (m_Options.Timeout > 0)
837
+ m_ProvideHandle.ResourceManager.AddUpdateReceiver(this);
838
+ #if ENABLE_ADDRESSABLE_PROFILER
839
+ AddBundleToProfiler(m_Source == BundleSource.Cache ? Profiling.ContentStatus.Loading : Profiling.ContentStatus.Downloading, m_Source);
840
+ #endif
841
+ m_RequestOperation.completed += WebRequestOperationCompleted;
842
+ }
843
+ }
844
+
845
+ public void Update(float unscaledDeltaTime)
846
+ {
847
+ if (m_RequestOperation != null && m_RequestOperation is UnityWebRequestAsyncOperation operation && !operation.isDone)
848
+ {
849
+ if (m_LastDownloadedByteCount != operation.webRequest.downloadedBytes)
850
+ {
851
+ m_TimeoutTimer = 0;
852
+ m_TimeoutOverFrames = 0;
853
+ m_LastDownloadedByteCount = operation.webRequest.downloadedBytes;
854
+ }
855
+ else
856
+ {
857
+ m_TimeoutTimer += unscaledDeltaTime;
858
+ if (HasTimedOut)
859
+ operation.webRequest.Abort();
860
+ m_TimeoutOverFrames++;
861
+ }
862
+ }
863
+ }
864
+
865
+ private void LocalRequestOperationCompleted(AsyncOperation op)
866
+ {
867
+ if (m_RequestCompletedCallbackCalled)
868
+ {
869
+ return;
870
+ }
871
+
872
+ m_RequestCompletedCallbackCalled = true;
873
+ CompleteBundleLoad((op as TTAssetBundleRequest).assetBundle);
874
+ }
875
+
876
+ private void CompleteBundleLoad(AssetBundle bundle)
877
+ {
878
+ m_AssetBundle = bundle;
879
+ #if ENABLE_ADDRESSABLE_PROFILER
880
+ AddBundleToProfiler(Profiling.ContentStatus.Active, m_Source);
881
+ #endif
882
+ if (m_AssetBundle != null)
883
+ m_ProvideHandle.Complete(this, true, null);
884
+ else
885
+ m_ProvideHandle.Complete<TTAssetBundleResource>(null, false,
886
+ new RemoteProviderException(string.Format("Invalid path in AssetBundleProvider: '{0}'.", m_TransformedInternalId), m_ProvideHandle.Location));
887
+ m_Completed = true;
888
+ }
889
+
890
+ private void WebRequestOperationCompleted(AsyncOperation op)
891
+ {
892
+ if (m_RequestCompletedCallbackCalled)
893
+ return;
894
+
895
+ m_RequestCompletedCallbackCalled = true;
896
+
897
+ if (m_Options.Timeout > 0)
898
+ m_ProvideHandle.ResourceManager.RemoveUpdateReciever(this);
899
+
900
+ UnityWebRequestAsyncOperation remoteReq = op as UnityWebRequestAsyncOperation;
901
+ var webReq = remoteReq?.webRequest;
902
+ var downloadHandler = webReq?.downloadHandler as DownloadHandlerTTAssetBundle;
903
+ TTUnityWebRequestResult uwrResult = null;
904
+ if (webReq != null && !TTUnityWebRequestUtilities.RequestHasErrors(webReq, out uwrResult))
905
+ {
906
+ if (!m_Completed)
907
+ {
908
+ #if ENABLE_ADDRESSABLE_PROFILER
909
+ AddBundleToProfiler(Profiling.ContentStatus.Active, m_Source);
910
+ #endif
911
+ m_AssetBundle = downloadHandler.assetBundle;
912
+ downloadHandler.Dispose();
913
+ downloadHandler = null;
914
+ m_ProvideHandle.Complete(this, true, null);
915
+ m_Completed = true;
916
+ }
917
+ #if ENABLE_CACHING
918
+ if (!string.IsNullOrEmpty(m_Options.Hash) && m_Options.ClearOtherCachedVersionsWhenLoaded)
919
+ Caching.ClearOtherCachedVersions(m_Options.BundleName, Hash128.Parse(m_Options.Hash));
920
+ #endif
921
+ }
922
+ else
923
+ {
924
+ if (HasTimedOut)
925
+ uwrResult.Error = "Request timeout";
926
+ webReq = m_WebRequestQueueOperation.m_WebRequest;
927
+ if (uwrResult == null)
928
+ uwrResult = new TTUnityWebRequestResult(m_WebRequestQueueOperation.m_WebRequest);
929
+
930
+ downloadHandler = webReq.downloadHandler as DownloadHandlerTTAssetBundle;
931
+ downloadHandler.Dispose();
932
+ downloadHandler = null;
933
+ bool forcedRetry = false;
934
+ string message = $"Web request failed, retrying ({m_Retries}/{m_Options.RetryCount})...\n{uwrResult}";
935
+ #if ENABLE_CACHING
936
+ if (!string.IsNullOrEmpty(m_Options.Hash))
937
+ {
938
+ #if ENABLE_ADDRESSABLE_PROFILER
939
+ if (m_Source == BundleSource.Cache)
940
+ #endif
941
+ {
942
+ message = $"Web request failed to load from cache. The cached AssetBundle will be cleared from the cache and re-downloaded. Retrying...\n{uwrResult}";
943
+ Caching.ClearCachedVersion(m_Options.BundleName, Hash128.Parse(m_Options.Hash));
944
+ if (m_Retries == 0 && uwrResult.ShouldRetryDownloadError())
945
+ {
946
+ Debug.LogFormat(message);
947
+ BeginOperation();
948
+ m_Retries++;
949
+ forcedRetry = true;
950
+ }
951
+ }
952
+ }
953
+ #endif
954
+ if (!forcedRetry)
955
+ {
956
+ if (m_Retries < m_Options.RetryCount && uwrResult.ShouldRetryDownloadError())
957
+ {
958
+ m_Retries++;
959
+ Debug.LogFormat(message);
960
+ BeginOperation();
961
+ }
962
+ else
963
+ {
964
+ var exception = new TTRemoteProviderException($"Unable to load asset bundle from : {webReq.url}", m_ProvideHandle.Location, uwrResult);
965
+ m_ProvideHandle.Complete<TTAssetBundleResource>(null, false, exception);
966
+ m_Completed = true;
967
+ #if ENABLE_ADDRESSABLE_PROFILER
968
+ RemoveBundleFromProfiler();
969
+ #endif
970
+ }
971
+ }
972
+ }
973
+
974
+ webReq.Dispose();
975
+ }
976
+
977
+ #if UNLOAD_BUNDLE_ASYNC
978
+ public bool Unload(out AssetBundleUnloadOperation unloadOp)
979
+ #else
980
+ public void Unload()
981
+ #endif
982
+ {
983
+ #if UNLOAD_BUNDLE_ASYNC
984
+ unloadOp = null;
985
+ if (m_AssetBundle != null)
986
+ {
987
+ unloadOp = m_AssetBundle.UnloadAsync(true);
988
+ m_AssetBundle = null;
989
+ }
990
+ #else
991
+ if (m_AssetBundle != null)
992
+ {
993
+ m_AssetBundle.TTUnload(true);
994
+ m_AssetBundle = null;
995
+ }
996
+ #endif
997
+ m_RequestOperation = null;
998
+ #if ENABLE_ADDRESSABLE_PROFILER
999
+ RemoveBundleFromProfiler();
1000
+ #endif
1001
+ #if UNLOAD_BUNDLE_ASYNC
1002
+ return unloadOp != null;
1003
+ #endif
1004
+ }
1005
+ }
1006
+
1007
+ [DisplayName("TTAssetBundle Provider")]
1008
+ public class TTAssetBundleProvider : ResourceProviderBase
1009
+ {
1010
+ #if UNLOAD_BUNDLE_ASYNC
1011
+ internal static Dictionary<string, AssetBundleUnloadOperation> m_UnloadingBundles = new Dictionary<string, AssetBundleUnloadOperation>();
1012
+
1013
+ [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
1014
+ private static void Init()
1015
+ {
1016
+ m_UnloadingBundles = new Dictionary<string, AssetBundleUnloadOperation>();
1017
+ }
1018
+
1019
+ protected internal static Dictionary<string, AssetBundleUnloadOperation> UnloadingBundles
1020
+ {
1021
+ get { return m_UnloadingBundles; }
1022
+ internal set { m_UnloadingBundles = value; }
1023
+ }
1024
+
1025
+ internal static int UnloadingAssetBundleCount => m_UnloadingBundles.Count;
1026
+ internal static int AssetBundleCount => AssetBundle.GetAllLoadedAssetBundles().Count() - UnloadingAssetBundleCount;
1027
+ internal static void WaitForAllUnloadingBundlesToComplete()
1028
+ {
1029
+ if (UnloadingAssetBundleCount > 0)
1030
+ {
1031
+ var bundles = m_UnloadingBundles.Values.ToArray();
1032
+ foreach (var b in bundles)
1033
+ b.WaitForCompletion();
1034
+ }
1035
+ }
1036
+
1037
+ #else
1038
+ internal static void WaitForAllUnloadingBundlesToComplete()
1039
+ {
1040
+ }
1041
+
1042
+ #endif
1043
+
1044
+ public override void Provide(ProvideHandle providerInterface)
1045
+ {
1046
+ #if UNLOAD_BUNDLE_ASYNC
1047
+ if (m_UnloadingBundles.TryGetValue(providerInterface.Location.InternalId, out var unloadOp))
1048
+ {
1049
+ if (unloadOp.isDone)
1050
+ unloadOp = null;
1051
+ }
1052
+ new TTAssetBundleResource().Start(providerInterface, unloadOp);
1053
+ #else
1054
+ new TTAssetBundleResource().Start(providerInterface);
1055
+ #endif
1056
+ }
1057
+
1058
+ public override Type GetDefaultType(IResourceLocation location)
1059
+ {
1060
+ return typeof(IAssetBundleResource);
1061
+ }
1062
+
1063
+ public override void Release(IResourceLocation location, object asset)
1064
+ {
1065
+ if (location == null)
1066
+ throw new ArgumentNullException("location");
1067
+ if (asset == null)
1068
+ {
1069
+ Debug.LogWarningFormat("Releasing null asset bundle from location {0}. This is an indication that the bundle failed to load.", location);
1070
+ return;
1071
+ }
1072
+
1073
+ var bundle = asset as TTAssetBundleResource;
1074
+ if (bundle != null)
1075
+ {
1076
+ #if UNLOAD_BUNDLE_ASYNC
1077
+ if (bundle.Unload(out var unloadOp))
1078
+ {
1079
+ m_UnloadingBundles.Add(location.InternalId, unloadOp);
1080
+ unloadOp.completed += op => m_UnloadingBundles.Remove(location.InternalId);
1081
+ }
1082
+ #else
1083
+ bundle.Unload();
1084
+ #endif
1085
+ return;
1086
+ }
1087
+ }
1088
+ }
1089
+ }
1090
+
1091
+
1092
+ namespace UnityEngine.ResourceManagement.Exceptions
1093
+ {
1094
+ /// <summary>
1095
+ /// Class representing an error occured during an operation that remotely fetch data.
1096
+ /// </summary>
1097
+ public class TTRemoteProviderException : ProviderException
1098
+ {
1099
+ /// <summary>
1100
+ /// Creates a new instance of <see cref="ProviderException"/>.
1101
+ /// </summary>
1102
+ /// <param name="message">A message describing the error.</param>
1103
+ /// <param name="location">The resource location that the operation was trying to provide.</param>
1104
+ /// <param name="uwrResult">The result of the unity web request, if any.</param>
1105
+ /// <param name="innerException">The exception that caused the error, if any.</param>
1106
+ public TTRemoteProviderException(string message, IResourceLocation location = null,
1107
+ TTUnityWebRequestResult uwrResult = null, Exception innerException = null)
1108
+ : base(message, location, innerException)
1109
+ {
1110
+ WebRequestResult = uwrResult;
1111
+ }
1112
+
1113
+ ///<inheritdoc/>
1114
+ public override string Message => this.ToString();
1115
+
1116
+ /// <summary>
1117
+ /// The result of the unity web request, if any.
1118
+ /// </summary>
1119
+ public TTUnityWebRequestResult WebRequestResult { get; }
1120
+
1121
+ /// <summary>Provides a new string object describing the exception.</summary>
1122
+ /// <returns>A newly allocated managed string.</returns>
1123
+ public override string ToString()
1124
+ {
1125
+ if (WebRequestResult != null)
1126
+ return
1127
+ $"{GetType().Name} : {base.Message}\nUnityWebRequest result : {WebRequestResult}\n{InnerException}";
1128
+ else
1129
+ return base.ToString();
1130
+ }
1131
+ }
1132
+ }
1133
+
1134
+ namespace UnityEngine.ResourceManagement.Util
1135
+ {
1136
+ internal class TTUnityWebRequestUtilities
1137
+ {
1138
+ public static bool RequestHasErrors(UnityWebRequest webReq, out TTUnityWebRequestResult result)
1139
+ {
1140
+ result = null;
1141
+ if (webReq == null || !webReq.isDone)
1142
+ return false;
1143
+
1144
+ #if UNITY_2020_1_OR_NEWER
1145
+ switch (webReq.result)
1146
+ {
1147
+ case UnityWebRequest.Result.InProgress:
1148
+ case UnityWebRequest.Result.Success:
1149
+ return false;
1150
+ case UnityWebRequest.Result.ConnectionError:
1151
+ case UnityWebRequest.Result.ProtocolError:
1152
+ case UnityWebRequest.Result.DataProcessingError:
1153
+ result = new TTUnityWebRequestResult(webReq);
1154
+ return true;
1155
+ default:
1156
+ throw new NotImplementedException($"Cannot determine whether UnityWebRequest succeeded or not from result : {webReq.result}");
1157
+ }
1158
+ #else
1159
+ var isError = webReq.isHttpError || webReq.isNetworkError;
1160
+ if (isError)
1161
+ result = new UnityWebRequestResult(webReq);
1162
+
1163
+ return isError;
1164
+ #endif
1165
+ }
1166
+
1167
+ internal static bool IsAssetBundleDownloaded(UnityWebRequestAsyncOperation op)
1168
+ {
1169
+ #if ENABLE_ASYNC_ASSETBUNDLE_UWR
1170
+ var handler = (DownloadHandlerAssetBundle)op.webRequest.downloadHandler;
1171
+ if (handler != null && handler.autoLoadAssetBundle)
1172
+ return handler.isDownloadComplete;
1173
+ #endif
1174
+ return op.isDone;
1175
+ }
1176
+ }
1177
+
1178
+ /// <summary>
1179
+ /// Container class for the result of a unity web request.
1180
+ /// </summary>
1181
+ public class TTUnityWebRequestResult
1182
+ {
1183
+ /// <summary>
1184
+ /// Creates a new instance of <see cref="UnityWebRequestResult"/>.
1185
+ /// </summary>
1186
+ /// <param name="request">The unity web request.</param>
1187
+ public TTUnityWebRequestResult(UnityWebRequest request)
1188
+ {
1189
+ string error = request.error;
1190
+ #if UNITY_2020_1_OR_NEWER
1191
+ if (request.result == UnityWebRequest.Result.DataProcessingError && request.downloadHandler != null)
1192
+ {
1193
+ error = $"{error} : {request.downloadHandler.error}";
1194
+ }
1195
+
1196
+ Result = request.result;
1197
+ #endif
1198
+ Error = error;
1199
+ ResponseCode = request.responseCode;
1200
+ Method = request.method;
1201
+ Url = request.url;
1202
+ }
1203
+
1204
+ /// <summary>Provides a new string object describing the result.</summary>
1205
+ /// <returns>A newly allocated managed string.</returns>
1206
+ public override string ToString()
1207
+ {
1208
+ var sb = new System.Text.StringBuilder();
1209
+
1210
+ #if UNITY_2020_1_OR_NEWER
1211
+ sb.AppendLine($"{Result} : {Error}");
1212
+ #else
1213
+ if (!string.IsNullOrEmpty(Error))
1214
+ sb.AppendLine(Error);
1215
+ #endif
1216
+ if (ResponseCode > 0)
1217
+ sb.AppendLine($"ResponseCode : {ResponseCode}, Method : {Method}");
1218
+ sb.AppendLine($"url : {Url}");
1219
+
1220
+ return sb.ToString();
1221
+ }
1222
+
1223
+ /// <summary>
1224
+ /// A string explaining the error that occured.
1225
+ /// </summary>
1226
+ public string Error { get; internal set; }
1227
+
1228
+ /// <summary>
1229
+ /// The numeric HTTP response code returned by the server, if any.
1230
+ /// See <a href="https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest-responseCode.html">documentation</a> for more details.
1231
+ /// </summary>
1232
+ public long ResponseCode { get; }
1233
+
1234
+ #if UNITY_2020_1_OR_NEWER
1235
+ /// <summary>
1236
+ /// The outcome of the request.
1237
+ /// </summary>
1238
+ public UnityWebRequest.Result Result { get; }
1239
+ #endif
1240
+ /// <summary>
1241
+ /// The HTTP verb used by this UnityWebRequest, such as GET or POST.
1242
+ /// </summary>
1243
+ public string Method { get; }
1244
+
1245
+ /// <summary>
1246
+ /// The target url of the request.
1247
+ /// </summary>
1248
+ public string Url { get; }
1249
+
1250
+ internal bool ShouldRetryDownloadError()
1251
+ {
1252
+ if (string.IsNullOrEmpty(Error))
1253
+ return true;
1254
+
1255
+ if (Error == "Request aborted" ||
1256
+ Error == "Unable to write data" ||
1257
+ Error == "Malformed URL" ||
1258
+ Error == "Out of memory" ||
1259
+ Error == "Encountered invalid redirect (missing Location header?)" ||
1260
+ Error == "Cannot modify request at this time" ||
1261
+ Error == "Unsupported Protocol" ||
1262
+ Error == "Destination host has an erroneous SSL certificate" ||
1263
+ Error == "Unable to load SSL Cipher for verification" ||
1264
+ Error == "SSL CA certificate error" ||
1265
+ Error == "Unrecognized content-encoding" ||
1266
+ Error == "Request already transmitted" ||
1267
+ Error == "Invalid HTTP Method" ||
1268
+ Error == "Header name contains invalid characters" ||
1269
+ Error == "Header value contains invalid characters" ||
1270
+ Error == "Cannot override system-specified headers"
1271
+ )
1272
+ return false;
1273
+
1274
+ /* Errors that can be retried:
1275
+ "Unknown Error":
1276
+ "No Internet Connection"
1277
+ "Backend Initialization Error":
1278
+ "Cannot resolve proxy":
1279
+ "Cannot resolve destination host":
1280
+ "Cannot connect to destination host":
1281
+ "Access denied":
1282
+ "Generic/unknown HTTP error":
1283
+ "Unable to read data":
1284
+ "Request timeout":
1285
+ "Error during HTTP POST transmission":
1286
+ "Unable to complete SSL connection":
1287
+ "Redirect limit exceeded":
1288
+ "Received no data in response":
1289
+ "Destination host does not support SSL":
1290
+ "Failed to transmit data":
1291
+ "Failed to receive data":
1292
+ "Login failed":
1293
+ "SSL shutdown failed":
1294
+ "Redirect limit is invalid":
1295
+ "Not implemented":
1296
+ "Data Processing Error, see Download Handler error":
1297
+ */
1298
+ return true;
1299
+ }
1300
+ }
1301
+ }