gg.easy.airship 0.1.2106 → 0.1.2108

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 (48) hide show
  1. package/AuthenticationForUnity/Runtime/Browser/AndroidBrowser.cs +85 -0
  2. package/AuthenticationForUnity/Runtime/Browser/AndroidBrowser.cs.meta +3 -0
  3. package/Editor/Accessories/Clothing/PlatformGearBundleManifestEditor.cs +36 -13
  4. package/Editor/BuildMenu.cs +44 -0
  5. package/Editor/CreateAssetBundles.cs +11 -0
  6. package/Editor/GameConfig/GameConfigEditor.cs +12 -0
  7. package/Editor/Packages/AirshipPackagesWindow.cs +44 -18
  8. package/Editor/Publish/API/CreateGameDeploymentDto.cs +1 -0
  9. package/Editor/Publish/API/DeploymentDto.cs +3 -0
  10. package/Editor/Publish/Deploy.cs +52 -41
  11. package/Runtime/Code/Auth/AuthManager.cs +2 -0
  12. package/Runtime/Code/Bootstrap/BundleDownloader.cs +8 -2
  13. package/Runtime/Code/Bootstrap/SignalHandler.cs +2 -0
  14. package/Runtime/Code/Bundles/AirshipPlatform.cs +1 -11
  15. package/Runtime/Code/Bundles/SystemRoot.cs +45 -5
  16. package/Runtime/Code/CoreUI/CoreLoadingScreen.prefab +25 -12
  17. package/Runtime/Code/CoreUI/Loading/CoreLoadingScreen.cs +8 -4
  18. package/Runtime/Code/CoreUI/Loading/LoadingQuitButton.cs +7 -0
  19. package/Runtime/Code/GameConfig/GameConfig.cs +2 -0
  20. package/Runtime/Code/Luau/AirshipComponent.cs +16 -3
  21. package/Runtime/Code/Luau/ReflectionList.cs +1 -1
  22. package/Runtime/Code/Misc/CanvasDistanceCondition.cs +2 -0
  23. package/Runtime/Code/Platform/Shared/AirshipInventoryServiceDto.cs +0 -2
  24. package/Runtime/Code/Player/Accessories/AccessoryBuilder.cs +8 -7
  25. package/Runtime/Code/Player/Character/Animation/CharacterAnimationHelper.cs +8 -8
  26. package/Runtime/Code/Player/OcclusionCam.cs +7 -5
  27. package/Runtime/Code/TSCodeGen/TypeGenerator.cs +1 -0
  28. package/Runtime/Code/Util/Singleton.cs +14 -20
  29. package/Runtime/Code/VoxelWorld/VoxelBlocks.cs +8 -1
  30. package/Runtime/Plugins/Android/libLuauPlugin.so +0 -0
  31. package/Runtime/Plugins/Android/libLuauPlugin.so.meta +61 -0
  32. package/Runtime/Plugins/Android.meta +8 -0
  33. package/Runtime/Plugins/Linux/libLuauPlugin.so +0 -0
  34. package/Runtime/Plugins/Linux/libLuauPlugin.so.meta +21 -40
  35. package/Runtime/Plugins/Mac/LuauPlugin.bundle/Contents/MacOS/LuauPlugin +0 -0
  36. package/Runtime/Plugins/Windows/x64/LuauPlugin.dll +0 -0
  37. package/Runtime/Plugins/Windows/x64/LuauPlugin.dll.meta +64 -1
  38. package/Runtime/Plugins/Windows/x64/LuauPlugin.pdb +0 -0
  39. package/Runtime/Plugins/iOS/LuauPluginIos.a +0 -0
  40. package/Runtime/Plugins/iOS/LuauPluginIos.a.meta +27 -39
  41. package/Runtime/Scenes/Login.unity +371 -315
  42. package/ThirdParty/AppleAuth/Editor/ProjectCapabilityManagerExtension.cs +58 -46
  43. package/ThirdParty/NativeGallery/Editor/NGPostProcessBuild.cs +7 -1
  44. package/ThirdParty/UiRoundedCorners/ImageWithIndependentRoundedCorners.cs +4 -1
  45. package/ThirdParty/UiRoundedCorners/ImageWithRoundedCorners.cs +5 -1
  46. package/URP/AirshipURPAssetBaked.asset +2 -2
  47. package/URP/Shaders/AirshipCharacterAlpha.shader +2 -3
  48. package/package.json +1 -1
@@ -0,0 +1,85 @@
1
+ using System;
2
+ using System.Net;
3
+ using System.Threading;
4
+ using System.Threading.Tasks;
5
+ using UnityEngine;
6
+
7
+ namespace Cdm.Authentication.Browser {
8
+ /// <summary>
9
+ /// OAuth 2.0 verification browser that runs a local server and waits for a call with
10
+ /// the authorization verification code.
11
+ /// </summary>
12
+ public class AndroidBrowser : IBrowser {
13
+ private string _prefix;
14
+
15
+ public AndroidBrowser(string prefix) {
16
+ _prefix = prefix;
17
+ }
18
+
19
+ private TaskCompletionSource<BrowserResult> _taskCompletionSource;
20
+
21
+ /// <summary>
22
+ /// Gets or sets the close page response. This HTML response is shown to the user after redirection is done.
23
+ /// </summary>
24
+ public string closePageResponse { get; set; } =
25
+ "<html><body><b>DONE!</b><br>(You can close this tab/window now)</body></html>";
26
+
27
+ public async Task<BrowserResult> StartAsync(string loginUrl, string redirectUrl, CancellationToken cancellationToken = default) {
28
+ _taskCompletionSource = new TaskCompletionSource<BrowserResult>();
29
+
30
+ cancellationToken.Register(() => {
31
+ _taskCompletionSource?.TrySetCanceled();
32
+ });
33
+
34
+ using var httpListener = new HttpListener();
35
+
36
+ try {
37
+ var prefix = _prefix;
38
+ prefix = AddForwardSlashIfNecessary(prefix);
39
+ httpListener.Prefixes.Add(prefix);
40
+ if (httpListener.IsListening) {
41
+ httpListener.Stop();
42
+ }
43
+ httpListener.Start();
44
+ httpListener.BeginGetContext(IncomingHttpRequest, httpListener);
45
+
46
+ Application.OpenURL(loginUrl);
47
+
48
+ return await _taskCompletionSource.Task;
49
+ } finally {
50
+ httpListener.Stop();
51
+ }
52
+ }
53
+
54
+ private void IncomingHttpRequest(IAsyncResult result) {
55
+ var httpListener = (HttpListener)result.AsyncState;
56
+ var httpContext = httpListener.EndGetContext(result);
57
+ var httpRequest = httpContext.Request;
58
+
59
+ // Build a response to send an "ok" back to the browser for the user to see.
60
+ var httpResponse = httpContext.Response;
61
+ var buffer = System.Text.Encoding.UTF8.GetBytes(closePageResponse);
62
+
63
+ // Send the output to the client browser.
64
+ httpResponse.ContentLength64 = buffer.Length;
65
+ var output = httpResponse.OutputStream;
66
+ output.Write(buffer, 0, buffer.Length);
67
+ output.Close();
68
+
69
+ _taskCompletionSource.SetResult(new BrowserResult(BrowserStatus.Success, httpRequest.Url.ToString()));
70
+ }
71
+
72
+ /// <summary>
73
+ /// Prefixes must end in a forward slash ("/")
74
+ /// </summary>
75
+ /// <see href="https://learn.microsoft.com/en-us/dotnet/api/system.net.httplistener?view=net-7.0#remarks" />
76
+ private string AddForwardSlashIfNecessary(string url) {
77
+ string forwardSlash = "/";
78
+ if (!url.EndsWith(forwardSlash)) {
79
+ url += forwardSlash;
80
+ }
81
+
82
+ return url;
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 8f64d370a4f941beaf2c599b91c73adc
3
+ timeCreated: 1741806451
@@ -26,6 +26,30 @@ namespace Editor.Accessories.Clothing {
26
26
  private static string easyOrgId = "6b62d6e3-9d74-449c-aeac-b4feed2012b1";
27
27
  private bool skipBuild = false;
28
28
 
29
+ [MenuItem("Airship/Internal/Publish All Platform Gear")]
30
+ public static async void PublishAllPlatformGearBundles() {
31
+ List<PlatformGearBundleManifest> gearBundles = new();
32
+
33
+ // Get all asset GUIDs
34
+ string[] guids = AssetDatabase.FindAssets("t:PlatformGearBundleManifest");
35
+ foreach (string guid in guids) {
36
+ string path = AssetDatabase.GUIDToAssetPath(guid);
37
+ var obj = AssetDatabase.LoadAssetAtPath<PlatformGearBundleManifest>(path);
38
+ if (obj != null) {
39
+ gearBundles.Add(obj);
40
+ }
41
+ }
42
+
43
+ int counter = 0;
44
+ foreach (var gearBundle in gearBundles) {
45
+ var editor = CreateEditor(gearBundle) as PlatformGearBundleManifestEditor;
46
+ await editor.BuildAllPlatforms();
47
+ counter++;
48
+ Debug.Log($"Gear publish progress: {counter}/{guids.Length}");
49
+ await Awaitable.WaitForSecondsAsync(0.1f);
50
+ }
51
+ }
52
+
29
53
  private void OnEnable() {
30
54
  skipBuild = false;
31
55
  }
@@ -45,7 +69,7 @@ namespace Editor.Accessories.Clothing {
45
69
  this.skipBuild = EditorGUILayout.Toggle("Skip Build", this.skipBuild);
46
70
  }
47
71
 
48
- private async void BuildAllPlatforms() {
72
+ public async Task BuildAllPlatforms() {
49
73
  var st = Stopwatch.StartNew();
50
74
  bool success = true;
51
75
 
@@ -109,22 +133,21 @@ namespace Editor.Accessories.Clothing {
109
133
  (string category, string subcategory) = GetGearCategory(gear);
110
134
 
111
135
  // Create a new class id
112
- var req = UnityWebRequest.PostWwwForm($"{AirshipPlatformUrl.contentService}/gear/resource-id/{easyOrgId}",
113
- JsonUtility.ToJson(new GearCreateRequest() {
114
- name = gear.name,
115
- imageId = "c0e07e88-09d4-4962-b42d-7794a7ad4cb2",
116
- description = "Clothing",
117
- gear = new GearCreateRequest() {
118
- airAssets = new string[]{},
119
- category = category,
120
- subcategory = subcategory
121
- }
122
- }));
136
+ var data = JsonUtility.ToJson(new GearCreateRequest() {
137
+ name = gear.name,
138
+ imageId = "64351892-40d4-409b-ab3a-501818213b50",
139
+ description = "Clothing",
140
+ airAssets = new string[] { },
141
+ category = category,
142
+ subcategory = subcategory,
143
+ });
144
+ var req = UnityWebRequest.Post($"{AirshipPlatformUrl.contentService}/gear/resource-id/{easyOrgId}", data, "application/json");
123
145
  req.SetRequestHeader("Authorization", "Bearer " + InternalHttpManager.editorAuthToken);
124
146
  req.SetRequestHeader("x-airship-ignore-rate-limit", "true");
125
147
  await req.SendWebRequest();
126
148
  if (req.result != UnityWebRequest.Result.Success) {
127
- Debug.LogError("Failed to update air asset: " + req.downloadHandler.text);
149
+ Debug.Log("Post request: " + data);
150
+ Debug.LogError("Failed to create gear class: " + req.downloadHandler.text);
128
151
  return;
129
152
  }
130
153
  Debug.Log("Create classId response: " + req.downloadHandler.text);
@@ -41,6 +41,8 @@ namespace Editor {
41
41
 
42
42
  private static void OnBuild() {
43
43
  PhysicsSetup.Setup(null);
44
+
45
+
44
46
  }
45
47
 
46
48
  public static void BuildLinuxServerStaging() {
@@ -218,6 +220,38 @@ namespace Editor {
218
220
  #endif
219
221
  }
220
222
 
223
+ public static void BuildAndroidClient(bool development) {
224
+ OnBuild();
225
+ CreateAssetBundles.ResetScenes();
226
+
227
+ PlayerSettings.SplashScreen.show = false;
228
+ PlayerSettings.SetScriptingBackend(NamedBuildTarget.Android, ScriptingImplementation.IL2CPP);
229
+ var options = new BuildPlayerOptions();
230
+ options.scenes = scenes;
231
+ options.locationPathName = $"build/client_android/{ClientExecutableName}.apk";
232
+ options.target = BuildTarget.Android;
233
+ if (development == true) {
234
+ options.options = BuildOptions.Development;
235
+ }
236
+
237
+ var report = BuildPipeline.BuildPlayer(options);
238
+ var summary = report.summary;
239
+ switch (summary.result) {
240
+ case BuildResult.Succeeded:
241
+ Debug.Log($"Build Android succeeded with size: {FormatBytes(summary)}");
242
+ EditorUtility.RevealInFinder(report.summary.outputPath);
243
+ break;
244
+ case BuildResult.Failed:
245
+ Debug.LogError("Build Android failed");
246
+ break;
247
+ default:
248
+ Debug.LogError("Build Android unexpected result:" + summary.result);
249
+ break;
250
+ }
251
+
252
+ CreateAssetBundles.AddAllGameBundleScenes();
253
+ }
254
+
221
255
  #if AIRSHIP_PLAYER
222
256
  [MenuItem("Airship/Create Binary/Client/iOS", priority = 80)]
223
257
  public static void BuildIOSClientMenuItem() {
@@ -228,6 +262,16 @@ namespace Editor {
228
262
  public static void BuildIOSDevelopmentClientMenuItem() {
229
263
  BuildIOSClient(true);
230
264
  }
265
+
266
+ [MenuItem("Airship/Create Binary/Client/Android", priority = 80)]
267
+ public static void BuildAndroidClientMenuItem() {
268
+ BuildAndroidClient(false);
269
+ }
270
+
271
+ [MenuItem("Airship/Create Binary/Client/Android (Development)", priority = 80)]
272
+ public static void BuildAndroidDevelopmentClientMenuItem() {
273
+ BuildAndroidClient(true);
274
+ }
231
275
  #endif
232
276
 
233
277
  public static void BuildWindowsClientStaging() {
@@ -10,6 +10,7 @@ using UnityEditor.Build.Pipeline;
10
10
  using UnityEditor.Build.Pipeline.Interfaces;
11
11
  using UnityEditor.Build.Pipeline.Tasks;
12
12
  using UnityEngine;
13
+ using UnityEngine.Rendering;
13
14
  #if UNITY_EDITOR
14
15
  using UnityEditor;
15
16
  #endif
@@ -356,8 +357,18 @@ public static class CreateAssetBundles {
356
357
  });
357
358
  }
358
359
  }
360
+
359
361
  // var tasks = DefaultBuildTasks.Create(DefaultBuildTasks.Preset.AssetBundleBuiltInShaderExtraction);
360
362
  var buildTarget = AirshipPlatformUtil.ToBuildTarget(platform);
363
+
364
+ if (platform == AirshipPlatform.Android) {
365
+ PlayerSettings.SetUseDefaultGraphicsAPIs(buildTarget, false);
366
+ PlayerSettings.SetGraphicsAPIs(buildTarget, new GraphicsDeviceType[]
367
+ {
368
+ GraphicsDeviceType.OpenGLES3
369
+ });
370
+ }
371
+
361
372
  var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget);
362
373
  if (platform is AirshipPlatform.Windows or AirshipPlatform.Mac or AirshipPlatform.Linux) {
363
374
  buildTargetGroup = BuildTargetGroup.Standalone;
@@ -17,6 +17,8 @@ public class GameConfigEditor : UnityEditor.Editor {
17
17
  private Action<UpdateSelectedGame> updateSelectedGame;
18
18
  private Action requestRefresh;
19
19
 
20
+ private SerializedProperty supportsMobile;
21
+
20
22
  Rect buttonRect;
21
23
  public override void OnInspectorGUI() {
22
24
  serializedObject.Update();
@@ -41,6 +43,14 @@ public class GameConfigEditor : UnityEditor.Editor {
41
43
  }
42
44
  GUILayout.EndHorizontal();
43
45
 
46
+ GUILayout.Space(20);
47
+ EditorGUILayout.LabelField("Platforms", EditorStyles.boldLabel);
48
+ EditorGUI.BeginDisabledGroup(true);
49
+ EditorGUILayout.Toggle(new GUIContent("Desktop"), true);
50
+ EditorGUI.EndDisabledGroup();
51
+ EditorGUILayout.PropertyField(this.supportsMobile, new GUIContent("Mobile"));
52
+ GUILayout.Space(20);
53
+
44
54
  foreach (var field in typeof(GameConfig).GetFields()) {
45
55
  if (field.Name is "gameId" or "gameLayers" || Attribute.IsDefined(field, typeof(HideInInspector))) continue; // Rendered above
46
56
 
@@ -95,6 +105,8 @@ public class GameConfigEditor : UnityEditor.Editor {
95
105
  markPublishTargetPinged = false;
96
106
  publishTargetPinged = true;
97
107
  }
108
+
109
+ this.supportsMobile = serializedObject.FindProperty("supportsMobile");
98
110
 
99
111
  updateSelectedGame += (update) => {
100
112
  var gameId = update.gameId;
@@ -24,6 +24,7 @@ using UnityEditor;
24
24
  using UnityEditor.Build.Pipeline;
25
25
  using UnityEngine;
26
26
  using UnityEngine.Networking;
27
+ using UnityEngine.Rendering;
27
28
  using Debug = UnityEngine.Debug;
28
29
  using Object = UnityEngine.Object;
29
30
  using ZipFile = Unity.VisualScripting.IonicZip.ZipFile;
@@ -373,27 +374,24 @@ namespace Editor.Packages {
373
374
  break;
374
375
  }
375
376
 
376
- var didVerify = AirshipPackagesWindow.VerifyBuildModules();
377
+ var didVerify = AirshipPackagesWindow.VerifyBuildModules(true);
377
378
  if (!didVerify) {
378
379
  Debug.LogErrorFormat("Missing build modules. Install missing modules in Unity Hub and restart Unity to publish package ({0}).", packageDoc.id);
379
380
  yield break;
380
381
  }
381
382
 
382
- // Sort the current platform first to speed up build time
383
383
  List<AirshipPlatform> platforms = new() {
384
- // AirshipPlatform.iOS,
384
+ AirshipPlatform.iOS,
385
385
  AirshipPlatform.Mac,
386
386
  AirshipPlatform.Windows,
387
+ AirshipPlatform.Android,
387
388
  };
388
- // var currentPlatform = AirshipPlatformUtil.GetLocalPlatform();
389
- // if (AirshipPlatformUtil.livePlatforms.Contains(currentPlatform)) {
390
- // platforms.Add(currentPlatform);
391
- // }
392
- // foreach (var platform in AirshipPlatformUtil.livePlatforms) {
393
- // if (platform == currentPlatform) continue;
394
- // platforms.Add(platform);
395
- // }
396
- // platforms.Remove(AirshipPlatform.Linux);
389
+ // Uncomment to just build iOS
390
+ if (isCoreMaterials) {
391
+ platforms.Clear();
392
+ // platforms.Add(AirshipPlatform.iOS);
393
+ platforms.Add(AirshipPlatform.Android);
394
+ }
397
395
 
398
396
  if (!CreateAssetBundles.PrePublishChecks()) {
399
397
  yield break;
@@ -426,6 +424,13 @@ namespace Editor.Packages {
426
424
  if (platform is AirshipPlatform.Windows or AirshipPlatform.Mac or AirshipPlatform.Linux) {
427
425
  buildTargetGroup = BuildTargetGroup.Standalone;
428
426
  }
427
+ if (platform == AirshipPlatform.Android) {
428
+ PlayerSettings.SetUseDefaultGraphicsAPIs(buildTarget, false);
429
+ PlayerSettings.SetGraphicsAPIs(buildTarget, new GraphicsDeviceType[]
430
+ {
431
+ GraphicsDeviceType.OpenGLES3
432
+ });
433
+ }
429
434
 
430
435
  var buildParams = new BundleBuildParameters(
431
436
  buildTarget,
@@ -435,7 +440,11 @@ namespace Editor.Packages {
435
440
  buildParams.UseCache = this.publishOptionUseCache;
436
441
  Debug.Log("Building package " + packageDoc.id + " with cache: " + this.publishOptionUseCache);
437
442
  if (isCoreMaterials) {
438
- buildParams.BundleCompression = BuildCompression.Uncompressed;
443
+ if (platform is AirshipPlatform.iOS or AirshipPlatform.Android) {
444
+ buildParams.BundleCompression = BuildCompression.LZ4;
445
+ } else {
446
+ buildParams.BundleCompression = BuildCompression.Uncompressed;
447
+ }
439
448
  } else {
440
449
  buildParams.BundleCompression = BuildCompression.LZ4;
441
450
  }
@@ -466,6 +475,10 @@ namespace Editor.Packages {
466
475
  }
467
476
  }
468
477
 
478
+ if (isCoreMaterials) {
479
+ yield break;
480
+ }
481
+
469
482
  var importsFolder = Path.Join("Assets", "AirshipPackages");
470
483
  var sourceAssetsFolder = Path.Join(importsFolder, packageDoc.id);
471
484
  var typesFolder = Path.Join(Path.Join("Assets", "AirshipPackages", "Types~"), packageDoc.id);
@@ -590,8 +603,11 @@ namespace Editor.Packages {
590
603
 
591
604
  // UploadSingleGameFile(urls.iOS_client_resources, $"{AirshipPlatform.iOS}/{orgScope}/{packageIdOnly}_client/resources", packageDoc),
592
605
  // UploadSingleGameFile(urls.iOS_client_scenes, $"{AirshipPlatform.iOS}/{orgScope}/{packageIdOnly}_client/scenes", packageDoc),
593
- // UploadSingleGameFile(urls.iOS_shared_resources, $"{AirshipPlatform.iOS}/{orgScope}/{packageIdOnly}_shared/resources", packageDoc),
594
- // UploadSingleGameFile(urls.iOS_shared_scenes, $"{AirshipPlatform.iOS}/{orgScope}/{packageIdOnly}_shared/scenes", packageDoc),
606
+ UploadSingleGameFile(urls.iOS_shared_resources, $"{AirshipPlatform.iOS}/{orgScope}/{packageIdOnly}_shared/resources", packageDoc),
607
+ UploadSingleGameFile(urls.iOS_shared_scenes, $"{AirshipPlatform.iOS}/{orgScope}/{packageIdOnly}_shared/scenes", packageDoc),
608
+
609
+ UploadSingleGameFile(urls.Android_shared_resources, $"{AirshipPlatform.Android}/{orgScope}/{packageIdOnly}_shared/resources", packageDoc),
610
+ UploadSingleGameFile(urls.Android_shared_scenes, $"{AirshipPlatform.Android}/{orgScope}/{packageIdOnly}_shared/scenes", packageDoc),
595
611
  });
596
612
  }
597
613
 
@@ -659,7 +675,8 @@ namespace Editor.Packages {
659
675
  // "Linux_shared_resources",
660
676
  "Mac_shared_resources",
661
677
  "Windows_shared_resources",
662
- // "iOS_shared_resources",
678
+ "iOS_shared_resources",
679
+ "Android_shared_resources",
663
680
 
664
681
  // "Linux_shared_scenes",
665
682
  // "Mac_shared_scenes",
@@ -690,7 +707,7 @@ namespace Editor.Packages {
690
707
  Repaint();
691
708
  }
692
709
 
693
- public static bool VerifyBuildModules() {
710
+ public static bool VerifyBuildModules(bool mobileSupport) {
694
711
  // var linux64 = ModuleUtil.IsModuleInstalled(BuildTarget.StandaloneLinux64);
695
712
  // if (!linux64) {
696
713
  // Debug.LogError("Linux Build Support (<b>Mono</b>) module not found.");
@@ -706,11 +723,20 @@ namespace Editor.Packages {
706
723
  Debug.LogError("Windows Build Support (<b>Mono</b>) module not found.");
707
724
  }
708
725
 
726
+ if (!mobileSupport) {
727
+ return mac && windows;
728
+ }
729
+
709
730
  var iOS = ModuleUtil.IsModuleInstalled(BuildTarget.iOS);
710
731
  if (!iOS) {
711
732
  Debug.LogError("iOS Build Support module not found.");
712
733
  }
713
- return mac && windows && iOS;
734
+
735
+ var android = ModuleUtil.IsModuleInstalled(BuildTarget.Android);
736
+ if (!iOS) {
737
+ Debug.LogError("Android Build Support module not found.");
738
+ }
739
+ return mac && windows && iOS && android;
714
740
  }
715
741
 
716
742
  private static IEnumerator UploadSingleGameFile(string url, string filePath, AirshipPackageDocument packageDoc, bool absoluteFilePath = false) {
@@ -8,6 +8,7 @@ public class CreateGameDeploymentDto {
8
8
  public bool deployCode;
9
9
  public bool deployAssets;
10
10
  public string[] packageSlugs;
11
+ public string[] platforms;
11
12
  }
12
13
 
13
14
  [Serializable]
@@ -40,6 +40,9 @@ public class DeploymentUrls {
40
40
  public string iOS_client_scenes;
41
41
  public string iOS_shared_scenes;
42
42
 
43
+ public string Android_shared_resources;
44
+ public string Android_shared_scenes;
45
+
43
46
  public string gameConfig;
44
47
  public string source;
45
48
  public string code;
@@ -35,31 +35,27 @@ public class Deploy {
35
35
  private static GameDto activeDeployTarget;
36
36
  public const ulong MAX_UPLOAD_KB = 500_000;
37
37
 
38
- public static void DeployToStaging()
38
+ public static void PublishGame()
39
39
  {
40
40
  // Make sure we generate and write all `NetworkPrefabCollection`s before we
41
41
  // build the game.
42
42
  // NetworkPrefabManager.WriteAllCollections();
43
43
  // Sort the current platform first to speed up build time
44
- List<AirshipPlatform> platforms = new() {
45
- // AirshipPlatform.iOS,
46
- #if UNITY_EDITOR_OSX // Run Mac build last if on OSX
47
- AirshipPlatform.Windows,
48
- AirshipPlatform.Mac,
49
- #else
50
- AirshipPlatform.Mac,
51
- AirshipPlatform.Windows,
52
- #endif
53
- };
54
- // List<AirshipPlatform> platforms = new();
55
- // var currentPlatform = AirshipPlatformUtil.GetLocalPlatform();
56
- // if (AirshipPlatformUtil.livePlatforms.Contains(currentPlatform)) {
57
- // platforms.Add(currentPlatform);
58
- // }
59
- // foreach (var platform in AirshipPlatformUtil.livePlatforms) {
60
- // if (platform == currentPlatform) continue;
61
- // platforms.Add(platform);
62
- // }
44
+ List<AirshipPlatform> platforms = new();
45
+ var gameConfig = GameConfig.Load();
46
+ if (gameConfig.supportsMobile) {
47
+ platforms.Add(AirshipPlatform.iOS);
48
+ platforms.Add(AirshipPlatform.Android);
49
+ }
50
+
51
+ // We want to end up on our editor machine's platform
52
+ #if UNITY_EDITOR_OSX
53
+ platforms.Add(AirshipPlatform.Windows);
54
+ platforms.Add(AirshipPlatform.Mac);
55
+ #else
56
+ platforms.Add(AirshipPlatform.Mac);
57
+ platforms.Add(AirshipPlatform.Windows);
58
+ #endif
63
59
  EditorCoroutines.Execute((BuildAndDeploy(platforms.ToArray(), false)));
64
60
  }
65
61
 
@@ -86,19 +82,21 @@ public class Deploy {
86
82
  yield break;
87
83
  }
88
84
 
85
+ var gameConfig = AssetDatabase.LoadAssetAtPath<GameConfig>("Assets/GameConfig.asset");
86
+ if (gameConfig == null) {
87
+ Debug.LogError("Missing GameConfig.");
88
+ yield break;
89
+ }
90
+
89
91
  if (!skipBuild) {
90
- var didVerify = AirshipPackagesWindow.VerifyBuildModules();
92
+ var didVerify = AirshipPackagesWindow.VerifyBuildModules(gameConfig.supportsMobile);
91
93
  if (!didVerify) {
92
94
  Debug.LogErrorFormat("Missing build modules. Install missing modules in Unity Hub and restart Unity to publish game.");
93
95
  yield break;
94
96
  }
95
97
  }
96
98
 
97
- var gameConfig = AssetDatabase.LoadAssetAtPath<GameConfig>("Assets/GameConfig.asset");
98
- if (gameConfig == null) {
99
- Debug.LogError("Missing GameConfig.");
100
- yield break;
101
- }
99
+
102
100
 
103
101
  var confirmedSaveState = EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
104
102
  if (!confirmedSaveState || SceneManager.GetActiveScene().isDirty) { // User clicked "cancel"
@@ -152,6 +150,13 @@ public class Deploy {
152
150
  DeploymentDto deploymentDto = null;
153
151
  string devKey = null;
154
152
  {
153
+ List<string> platformStrings = new();
154
+ platformStrings.Add("Mac");
155
+ platformStrings.Add("Windows");
156
+ if (gameConfig.supportsMobile) {
157
+ platformStrings.Add("iOS");
158
+ platformStrings.Add("Android");
159
+ }
155
160
  var packageSlugs = gameConfig.packages.Select((p) => p.id);
156
161
  for (int i = 0; i < possibleKeys.Count; i++) {
157
162
  devKey = possibleKeys[i];
@@ -163,7 +168,8 @@ public class Deploy {
163
168
  defaultScene = gameConfig.startingScene.name,
164
169
  deployCode = true,
165
170
  deployAssets = platforms.Length > 0,
166
- packageSlugs = packageSlugs.ToArray()
171
+ packageSlugs = packageSlugs.ToArray(),
172
+ platforms = platformStrings.ToArray(),
167
173
  }), "application/json");
168
174
  req.SetRequestHeader("Authorization", "Bearer " + devKey);
169
175
  yield return req.SendWebRequest();
@@ -300,8 +306,11 @@ public class Deploy {
300
306
 
301
307
  // UploadSingleGameFile(urls.iOS_client_resources, $"{AirshipPlatform.iOS}/client/resources", AirshipPlatform.iOS),
302
308
  // UploadSingleGameFile(urls.iOS_client_scenes, $"{AirshipPlatform.iOS}/client/scenes", AirshipPlatform.iOS),
303
- // UploadSingleGameFile(urls.iOS_shared_resources, $"{AirshipPlatform.iOS}/shared/resources", AirshipPlatform.iOS),
304
- // UploadSingleGameFile(urls.iOS_shared_scenes, $"{AirshipPlatform.iOS}/shared/scenes", AirshipPlatform.iOS),
309
+ UploadSingleGameFile(urls.iOS_shared_resources, $"{AirshipPlatform.iOS}/shared/resources", AirshipPlatform.iOS),
310
+ UploadSingleGameFile(urls.iOS_shared_scenes, $"{AirshipPlatform.iOS}/shared/scenes", AirshipPlatform.iOS),
311
+
312
+ UploadSingleGameFile(urls.Android_shared_resources, $"{AirshipPlatform.Android}/shared/resources", AirshipPlatform.Android),
313
+ UploadSingleGameFile(urls.Android_shared_scenes, $"{AirshipPlatform.Android}/shared/scenes", AirshipPlatform.Android),
305
314
  });
306
315
  }
307
316
 
@@ -381,6 +390,18 @@ public class Deploy {
381
390
 
382
391
  // Complete deployment
383
392
  {
393
+ List<string> uploadedFileIds = new();
394
+ uploadedFileIds.Add("Mac_shared_resources");
395
+ uploadedFileIds.Add("Mac_shared_scenes");
396
+ uploadedFileIds.Add("Windows_shared_resources");
397
+ uploadedFileIds.Add("Windows_shared_scenes");
398
+ if (gameConfig.supportsMobile) {
399
+ uploadedFileIds.Add("iOS_shared_resources");
400
+ uploadedFileIds.Add("iOS_shared_scenes");
401
+ uploadedFileIds.Add("Android_shared_resources");
402
+ uploadedFileIds.Add("Android_shared_scenes");
403
+ }
404
+
384
405
  int attemptNum = 0;
385
406
  while (attemptNum < 5) {
386
407
  // Debug.Log("Complete. GameId: " + gameConfig.gameId + ", assetVersionId: " + deploymentDto.version.assetVersionNumber);
@@ -389,17 +410,7 @@ public class Deploy {
389
410
  new CompleteGameDeploymentDto() {
390
411
  gameId = gameConfig.gameId,
391
412
  gameVersionId = deploymentDto.version.gameVersionId,
392
- uploadedFileIds = new [] {
393
- // "Linux_shared_resources",
394
- "Mac_shared_resources",
395
- "Windows_shared_resources",
396
- // "iOS_shared_resources",
397
-
398
- // "Linux_shared_scenes",
399
- "Mac_shared_scenes",
400
- "Windows_shared_scenes",
401
- // "iOS_shared_scenes",
402
- },
413
+ uploadedFileIds = uploadedFileIds.ToArray(),
403
414
  }), "application/json");
404
415
  req.SetRequestHeader("Authorization", "Bearer " + devKey);
405
416
  yield return req.SendWebRequest();
@@ -617,7 +628,7 @@ public class Deploy {
617
628
 
618
629
  switch (option) {
619
630
  case 0: // Publish
620
- Deploy.DeployToStaging();
631
+ Deploy.PublishGame();
621
632
  break;
622
633
  case 1: // Cancel
623
634
  break;
@@ -121,6 +121,8 @@ public class AuthManager {
121
121
  crossPlatformBrowser.platformBrowsers.Add(RuntimePlatform.OSXEditor, standaloneBrowser);
122
122
  crossPlatformBrowser.platformBrowsers.Add(RuntimePlatform.OSXPlayer, standaloneBrowser);
123
123
  crossPlatformBrowser.platformBrowsers.Add(RuntimePlatform.IPhonePlayer, new ASWebAuthenticationSessionBrowser());
124
+ // crossPlatformBrowser.platformBrowsers.Add(RuntimePlatform.Android, new DeepLinkBrowser());
125
+ crossPlatformBrowser.platformBrowsers.Add(RuntimePlatform.Android, new AndroidBrowser("http://*:8080"));
124
126
 
125
127
  using var authenticationSession = new AuthenticationSession(auth, crossPlatformBrowser);
126
128
 
@@ -92,9 +92,15 @@ public class BundleDownloader : Singleton<BundleDownloader> {
92
92
 
93
93
  long totalBytes = 0;
94
94
  foreach (var request in preRequests) {
95
+ if (request.webRequest.result != UnityWebRequest.Result.Success) continue;
96
+
95
97
  var contentLength = request.webRequest.GetResponseHeader("content-length");
96
- var bytes = long.Parse(contentLength);
97
- totalBytes += bytes;
98
+ try {
99
+ var bytes = long.Parse(contentLength);
100
+ totalBytes += bytes;
101
+ } catch (Exception e) {
102
+ Debug.LogError("Failed to parse content-length header: " + e);
103
+ }
98
104
  }
99
105
 
100
106
  if (loadingScreen) {
@@ -1,8 +1,10 @@
1
1
  using System.Collections;
2
2
  using System.Threading;
3
3
  using Code.Util;
4
+ #if UNITY_STANDALONE_LINUX || UNITY_EDITOR_LINUX
4
5
  using Mono.Unix;
5
6
  using Mono.Unix.Native;
7
+ #endif
6
8
  using UnityEngine;
7
9
 
8
10
  namespace Code.Bootstrap {
@@ -16,21 +16,11 @@ namespace Code.Bootstrap {
16
16
  public class AirshipPlatformUtil {
17
17
  public static AirshipPlatform[] livePlatforms = new[]
18
18
  {
19
- // AirshipPlatform.iOS,
20
- AirshipPlatform.Mac,
21
- AirshipPlatform.Windows,
22
- AirshipPlatform.Linux
23
- };
24
-
25
- /// <summary>
26
- /// Just another list that includes mobile.
27
- /// You probably shouldn't use this -- instead use livePlatforms.
28
- /// </summary>
29
- public static AirshipPlatform[] betaPlatforms = new[] {
30
19
  AirshipPlatform.iOS,
31
20
  AirshipPlatform.Mac,
32
21
  AirshipPlatform.Windows,
33
22
  AirshipPlatform.Linux,
23
+ AirshipPlatform.Android,
34
24
  };
35
25
 
36
26
  public static string GetStringName(AirshipPlatform platform) {