gg.easy.airship 0.1.2193 → 0.1.2195

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 (76) hide show
  1. package/Editor/Accessories/Clothing/PlatformGearBundleManifestEditor.cs +7 -1
  2. package/Editor/CreateAssetBundles.cs +5 -11
  3. package/Editor/Publish/Callback/IBuildAirshipGameBundle.cs +49 -0
  4. package/Editor/Publish/Callback/IBuildAirshipGameBundle.cs.meta +3 -0
  5. package/Editor/Publish/Callback.meta +3 -0
  6. package/Editor/Publish/Deploy.cs +28 -21
  7. package/Editor/Quality/QualityConfig.cs +39 -12
  8. package/Editor/Settings/AirshipSettingsProvider.cs +28 -2
  9. package/Runtime/Code/AirshipConst.cs +3 -2
  10. package/Runtime/Code/Bootstrap/ServerBootstrap.cs +4 -0
  11. package/Runtime/Code/Bundles/SystemRoot.cs +11 -1
  12. package/Runtime/Code/CoreUI/Components/AirshipVersionOverlay.cs +26 -0
  13. package/Runtime/Code/CoreUI/Components/AirshipVersionOverlay.cs.meta +3 -0
  14. package/Runtime/Code/Luau/LuauAssembly/BinaryBlob.cs +2 -1
  15. package/Runtime/Code/Luau/LuauCore.cs +25 -1
  16. package/Runtime/Code/Luau/LuauCoreCallbacks.cs +11 -0
  17. package/Runtime/Code/LuauAPI/GameObjectAPI.cs +15 -4
  18. package/Runtime/Code/LuauAPI/TransformAPI.cs +14 -2
  19. package/Runtime/Code/LuauHelper/LuauHelper.cs +9 -1
  20. package/Runtime/Code/Network/Net.cs +9 -3
  21. package/Runtime/Code/Network/Simulation/AirshipNetworkedObject.cs +1 -3
  22. package/Runtime/Code/Network/Simulation/AirshipSimulationManager.cs +10 -7
  23. package/Runtime/Code/Network/Simulation/History.cs +3 -3
  24. package/Runtime/Code/Network/StateSystem/AirshipNetworkedStateManager.cs +138 -123
  25. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestMovementInputDiff.cs +7 -0
  26. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestMovementInputDiff.cs.meta +3 -0
  27. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestMovementInputGroup.cs +16 -0
  28. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestMovementInputGroup.cs.meta +3 -0
  29. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestNetworkedStateManager.cs +7 -5
  30. package/Runtime/Code/Network/StateSystem/Structures/InputCommand.cs +9 -0
  31. package/Runtime/Code/Network/StateSystem/Structures/InputCommandDiff.cs +13 -0
  32. package/Runtime/Code/Network/StateSystem/Structures/InputCommandDiff.cs.meta +3 -0
  33. package/Runtime/Code/Network/StateSystem/Structures/InputCommandGroup.cs +43 -0
  34. package/Runtime/Code/Network/StateSystem/Structures/InputCommandGroup.cs.meta +3 -0
  35. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterMovement.cs +68 -167
  36. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterNetworkedStateManager.cs +5 -6
  37. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterPhysics.cs +2 -2
  38. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputData.cs +113 -2
  39. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputDiff.cs +56 -0
  40. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputDiff.cs.meta +3 -0
  41. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputGroup.cs +27 -0
  42. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputGroup.cs.meta +3 -0
  43. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterSnapshotData.cs +30 -41
  44. package/Runtime/Code/Quality/QualityManager.cs +5 -5
  45. package/Runtime/Code/UI/Canvas/CanvasUIEventInterceptor.cs +14 -14
  46. package/Runtime/Code/VoxelWorld/Resources/VoxelWorldMatURP.mat +3 -3
  47. package/Runtime/Code/VoxelWorld/VoxelBlockDefinition.cs +1 -0
  48. package/Runtime/Code/VoxelWorld/VoxelBlockDefinitionList.cs +1 -0
  49. package/Runtime/Code/VoxelWorld/VoxelBlocks.cs +2 -0
  50. package/Runtime/Code/VoxelWorld/VoxelMeshProcessor.cs +11 -6
  51. package/Runtime/Code/VoxelWorld/VoxelWorld.cs +44 -24
  52. package/Runtime/Code/VoxelWorld/VoxelWorldChunk.cs +4 -1
  53. package/Runtime/Code/VoxelWorld/VoxelWorldEditorConfig.cs +13 -0
  54. package/Runtime/Code/VoxelWorld/VoxelWorldEditorConfig.cs.meta +3 -0
  55. package/Runtime/Code/VoxelWorld/VoxelWorldNetworker.cs +2 -0
  56. package/Runtime/Plugins/Android/libLuauPlugin.so +0 -0
  57. package/Runtime/Plugins/Linux/libLuauPlugin.so +0 -0
  58. package/Runtime/Plugins/Mac/LuauPlugin.bundle/Contents/Info.plist +7 -7
  59. package/Runtime/Plugins/Mac/LuauPlugin.bundle/Contents/MacOS/LuauPlugin +0 -0
  60. package/Runtime/Plugins/Windows/x64/LuauPlugin.dll +0 -0
  61. package/Runtime/Plugins/iOS/LuauPluginIos.a +0 -0
  62. package/Runtime/Scenes/CoreScene.unity +262 -649
  63. package/ThirdParty/Mirror/Core/NetworkClient.cs +9 -3
  64. package/ThirdParty/Mirror/Core/NetworkClient_TimeInterpolation.cs +1 -1
  65. package/ThirdParty/Mirror/Core/NetworkConnectionToClient.cs +6 -0
  66. package/ThirdParty/Mirror/Core/NetworkServer.cs +6 -4
  67. package/ThirdParty/Mirror/Core/Tools/SimpleMovingAverage.cs +42 -0
  68. package/ThirdParty/Mirror/Core/Tools/SimpleMovingAverage.cs.meta +3 -0
  69. package/ThirdParty/UiRoundedCorners/ImageWithIndependentRoundedCorners.cs +1 -0
  70. package/ThirdParty/UiRoundedCorners/ImageWithRoundedCorners.cs +1 -0
  71. package/URP/AirshipLowestURPAsset_Renderer.asset +1 -1
  72. package/URP/AirshipMobileURPAsset.asset +2 -0
  73. package/URP/AirshipMobileURPAsset_Renderer.asset +3 -3
  74. package/URP/AirshipURPAsset.asset +4 -2
  75. package/URP/AirshipURPAsset_Renderer.asset +3 -3
  76. package/package.json +1 -1
@@ -23,7 +23,13 @@ namespace Editor.Accessories.Clothing {
23
23
  [CustomEditor(typeof(PlatformGearBundleManifest))]
24
24
  [CanEditMultipleObjects]
25
25
  public class PlatformGearBundleManifestEditor : UnityEditor.Editor {
26
+ #if AIRSHIP_STAGING
27
+ private static string easyOrgId = "6536df9f3843ac629cf3b8b1";
28
+ private static string defaultImageId = "b5f260d4-2678-4255-b9bd-9136dd3edf36";
29
+ #else
26
30
  private static string easyOrgId = "6b62d6e3-9d74-449c-aeac-b4feed2012b1";
31
+ private static string defaultImageId = "64351892-40d4-409b-ab3a-501818213b50";
32
+ #endif
27
33
  private bool skipBuild = false;
28
34
 
29
35
  [MenuItem("Airship/Internal/Publish All Platform Gear")]
@@ -140,7 +146,7 @@ namespace Editor.Accessories.Clothing {
140
146
  // Create a new class id
141
147
  var data = JsonUtility.ToJson(new GearCreateRequest() {
142
148
  name = gear.name,
143
- imageId = "64351892-40d4-409b-ab3a-501818213b50",
149
+ imageId = defaultImageId,
144
150
  description = "Clothing",
145
151
  airAssets = new string[] { },
146
152
  category = category,
@@ -5,6 +5,7 @@ using System.IO;
5
5
  using System.Linq;
6
6
  using Code.Bootstrap;
7
7
  using Editor.Packages;
8
+ using Editor.Publish.Callback;
8
9
  using UnityEditor.Build.Pipeline;
9
10
  using UnityEditor.Build.Pipeline.Interfaces;
10
11
  using UnityEditor.Build.Pipeline.Tasks;
@@ -344,9 +345,7 @@ public static class CreateAssetBundles {
344
345
  addressableNames = addressableNames
345
346
  };
346
347
  builds.Add(build);
347
- } else {
348
- if (assetBundleName != "shared/resources") continue;
349
-
348
+ } else if (assetBundleName == "shared/resources") {
350
349
  var assetGuids = AssetDatabase.FindAssets("*", new string[] {"Assets/Resources"}).ToHashSet();
351
350
  if (AssetDatabase.AssetPathExists("Assets/Airship.asbuildinfo")) {
352
351
  assetGuids.Add(AssetDatabase.AssetPathToGUID("Assets/Airship.asbuildinfo"));
@@ -416,14 +415,6 @@ public static class CreateAssetBundles {
416
415
  buildParams.BundleCompression = BuildCompression.LZ4;
417
416
  var buildContent = new BundleBuildContent(builds);
418
417
 
419
- // Debug.Log("Additional files:");
420
- // foreach (var pair in buildContent.AdditionalFiles) {
421
- // Debug.Log(pair.Key + ":");
422
- // foreach (var p in pair.Value) {
423
- // Debug.Log(" - " + p.fileAlias);
424
- // }
425
- // }
426
-
427
418
  ContentPipeline.BuildCallbacks.PostPackingCallback = (parameters, data, arg3) => {
428
419
  return ReturnCode.Success;
429
420
  };
@@ -431,6 +422,9 @@ public static class CreateAssetBundles {
431
422
  AirshipPackagesWindow.buildingPackageId = "game";
432
423
  buildingBundles = true;
433
424
  AirshipScriptableBuildPipelineConfig.buildingGameBundles = true;
425
+ // Allow other logic to hook into pre build game bundles (used for setting up scriptable shader
426
+ // scripting based on target).
427
+ BuildAirshipGameBundleProcessor.InvokePreBuildGameBundle(buildTarget);
434
428
  ReturnCode returnCode = ContentPipeline.BuildAssetBundles(buildParams, buildContent, out var result);
435
429
  buildingBundles = false;
436
430
  AirshipScriptableBuildPipelineConfig.buildingGameBundles = false;
@@ -0,0 +1,49 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Linq;
4
+ using System.Reflection;
5
+ using UnityEditor;
6
+ using UnityEditor.Build;
7
+ using UnityEngine;
8
+
9
+ namespace Editor.Publish.Callback {
10
+ public interface IBuildAirshipGameBundle : IOrderedCallback {
11
+ /// <summary>
12
+ /// Fired before building asset bundles for game
13
+ /// </summary>
14
+ void OnPreBuildGameBundle(BuildTarget buildTarget);
15
+ }
16
+
17
+ [InitializeOnLoad]
18
+ public static class BuildAirshipGameBundleProcessor {
19
+ private static List<IBuildAirshipGameBundle> callbacks;
20
+
21
+ static BuildAirshipGameBundleProcessor() {
22
+ callbacks = GetCallbackInstances();
23
+ }
24
+
25
+ public static void InvokePreBuildGameBundle(BuildTarget target) {
26
+ foreach (var callback in callbacks) {
27
+ try {
28
+ callback.OnPreBuildGameBundle(target);
29
+ } catch (Exception e) {
30
+ Debug.LogError(e);
31
+ }
32
+ }
33
+ }
34
+
35
+ /// <summary>
36
+ /// Create instances of each implementation of IBuildAirshipGameBundle
37
+ /// </summary>
38
+ private static List<IBuildAirshipGameBundle> GetCallbackInstances() {
39
+ var instances = new List<IBuildAirshipGameBundle>();
40
+
41
+ var derivedTypes = TypeCache.GetTypesDerivedFrom<IBuildAirshipGameBundle>();
42
+ foreach (var type in derivedTypes) {
43
+ var instance = (IBuildAirshipGameBundle) Activator.CreateInstance(type);
44
+ instances.Add(instance);
45
+ }
46
+ return instances.OrderBy(i => i.callbackOrder).ToList();
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: f2e2ed287f3d4bf3b9c35d62abcf1ae0
3
+ timeCreated: 1762807654
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: e745493002eb40668673cc8bce661f2f
3
+ timeCreated: 1762807626
@@ -51,21 +51,7 @@ public class Deploy {
51
51
  // Sort the current platform first to speed up build time
52
52
  List<AirshipPlatform> platforms = new();
53
53
 
54
- #if UNITY_EDITOR_OSX
55
- platforms.Add(AirshipPlatform.Windows);
56
- platforms.Add(AirshipPlatform.Mac);
57
- #else
58
- platforms.Add(AirshipPlatform.Windows);
59
- platforms.Add(AirshipPlatform.Mac);
60
- #endif
61
-
62
- var gameConfig = GameConfig.Load();
63
- if (gameConfig.supportsMobile) {
64
- platforms.Add(AirshipPlatform.iOS);
65
- platforms.Add(AirshipPlatform.Android);
66
- }
67
-
68
- EditorCoroutines.Execute((BuildAndDeploy(platforms.ToArray(), false)));
54
+ EditorCoroutines.Execute(BuildAndDeploy());
69
55
  }
70
56
 
71
57
  [MenuItem("Airship/Misc/Build Game Asset Bundle")]
@@ -86,12 +72,8 @@ public class Deploy {
86
72
  }
87
73
 
88
74
  [MenuItem("Airship/Publish Game (No Cache)", priority = 51)]
89
- public static void PublishWithoutCache()
90
- {
91
- // Make sure we generate and write all `NetworkPrefabCollection`s before we
92
- // build the game.
93
- // NetworkPrefabManager.WriteAllCollections();
94
- EditorCoroutines.Execute((BuildAndDeploy(AirshipPlatformUtil.livePlatforms, false, false)));
75
+ public static void PublishWithoutCache() {
76
+ EditorCoroutines.Execute(BuildAndDeploy(false, false));
95
77
  }
96
78
 
97
79
  private static string GetDeployKey(DeployAuthType authType) {
@@ -106,6 +88,28 @@ public class Deploy {
106
88
  throw new Exception($"[Airship] Unknown auth type: {authType}");
107
89
  }
108
90
 
91
+ /// <summary>
92
+ /// BuildAndDeploy with the target platforms defined in GameConfig. Should only be used in asset deployments
93
+ /// (not code only).
94
+ /// </summary>
95
+ private static IEnumerator BuildAndDeploy(bool skipBuild = false, bool useCache = true, bool dontUpload = false) {
96
+ var platforms = new List<AirshipPlatform>();
97
+ #if UNITY_EDITOR_OSX
98
+ platforms.Add(AirshipPlatform.Windows);
99
+ platforms.Add(AirshipPlatform.Mac);
100
+ #else
101
+ platforms.Add(AirshipPlatform.Windows);
102
+ platforms.Add(AirshipPlatform.Mac);
103
+ #endif
104
+
105
+ var gameConfig = GameConfig.Load();
106
+ if (gameConfig.supportsMobile) {
107
+ platforms.Add(AirshipPlatform.iOS);
108
+ platforms.Add(AirshipPlatform.Android);
109
+ }
110
+ return BuildAndDeploy(platforms.ToArray(), skipBuild, useCache, dontUpload);
111
+ }
112
+
109
113
  private static IEnumerator BuildAndDeploy(AirshipPlatform[] platforms, bool skipBuild = false, bool useCache = true, bool dontUpload = false) {
110
114
  var possibleKeys = new List<string> { GetDeployKey(DeployAuthType.DeployKey), GetDeployKey(DeployAuthType.EditorAuthToken) };
111
115
  possibleKeys.RemoveAll(string.IsNullOrEmpty);
@@ -345,6 +349,9 @@ public class Deploy {
345
349
  var success = CreateAssetBundles.BuildPlatforms(platforms, useCache);
346
350
  if (!success) {
347
351
  Debug.Log("Cancelled publish.");
352
+
353
+ // Switch back to starting build target
354
+ EditorUserBuildSettings.SwitchActiveBuildTarget(startingBuildGroup, startingBuildTarget);
348
355
  yield break;
349
356
  }
350
357
 
@@ -1,6 +1,7 @@
1
1
  #if UNITY_EDITOR
2
2
  using System;
3
3
  using UnityEditor;
4
+ using UnityEditor.Build;
4
5
  using UnityEngine;
5
6
  using UnityEngine.Rendering;
6
7
  using UnityEngine.Rendering.Universal;
@@ -16,7 +17,14 @@ namespace Editor.Quality {
16
17
  [MenuItem("Airship/Quality/Config Mobile")]
17
18
  #endif
18
19
  public static void ConfigureLowQualityLevel() {
19
- SwapToQualityLevel(LOW_QUALITY_NAME);
20
+ var index = GetOrCreateQualityLevel(LOW_QUALITY_NAME);
21
+ // Switch to it so QualitySettings.* edits apply to the right level
22
+ QualitySettings.SetQualityLevel(index, true);
23
+ ConfigureSupportedPlatforms(index,
24
+ new []{ NamedBuildTarget.Android, NamedBuildTarget.iOS, },
25
+ new []{ NamedBuildTarget.Standalone }
26
+ );
27
+
20
28
  ConfigureForLow();
21
29
  SaveChangesToQualitySettings();
22
30
  }
@@ -25,11 +33,31 @@ namespace Editor.Quality {
25
33
  [MenuItem("Airship/Quality/Config Normal")]
26
34
  #endif
27
35
  public static void ConfigureNormalQualityLevel() {
28
- SwapToQualityLevel(NORMAL_QUALITY_NAME);
36
+ var index = GetOrCreateQualityLevel(NORMAL_QUALITY_NAME);
37
+ // Switch to it so QualitySettings.* edits apply to the right level
38
+ QualitySettings.SetQualityLevel(index, true);
39
+ ConfigureSupportedPlatforms(index,
40
+ new []{ NamedBuildTarget.Standalone },
41
+ new []{ NamedBuildTarget.Android, NamedBuildTarget.iOS, }
42
+ );
43
+
29
44
  ConfigureForNormal();
30
45
  SaveChangesToQualitySettings();
31
46
  }
32
47
 
48
+ private static void ConfigureSupportedPlatforms(int index, NamedBuildTarget[] included, NamedBuildTarget[] excluded) {
49
+ foreach (var target in included) {
50
+ if (!QualitySettings.TryIncludePlatformAt(target.TargetName, index, out var ex)) {
51
+ Debug.LogError($"Failed to configure included platforms for quality level: {ex}");
52
+ }
53
+ }
54
+ foreach (var target in excluded) {
55
+ if (!QualitySettings.TryExcludePlatformAt(target.TargetName, index, out var ex)) {
56
+ Debug.LogError($"Failed to configure excluded platforms for quality level: {ex}");
57
+ }
58
+ }
59
+ }
60
+
33
61
  private static void ConfigureForLow() {
34
62
  // At a value of 1 this reduces the max texture mipmap level to half resolution.
35
63
  QualitySettings.globalTextureMipmapLimit = 1;
@@ -88,21 +116,20 @@ namespace Editor.Quality {
88
116
  pipeline.shadowCascadeCount = 2;
89
117
  pipeline.cascade4Split = new Vector3(0.067f, 0.2f, 0.467f);
90
118
  }
91
-
92
- private static void SwapToQualityLevel(string name) {
93
- int index = GetQualityIndex(name);
119
+
120
+ /// <summary>
121
+ /// Returns the index of the quality level with given name. Will create a new quality level if none
122
+ /// exist with the name.
123
+ /// </summary>
124
+ private static int GetOrCreateQualityLevel(string name) {
125
+ var index = GetQualityIndex(name);
94
126
  if (index < 0) {
95
127
  if (!TryAddQualityLevel(name, out index)) {
96
- Debug.LogError("Failed to add Mobile quality level. See console for details.");
97
- return;
128
+ throw new Exception("Failed to create quality level.");
98
129
  }
99
130
  Debug.Log($"Created quality level '{name}' at index {index}.");
100
- } else {
101
- Debug.Log($"Found existing quality level '{name}' at index {index}.");
102
131
  }
103
-
104
- // Switch to it so QualitySettings.* edits apply to the right level
105
- QualitySettings.SetQualityLevel(index, true);
132
+ return index;
106
133
  }
107
134
 
108
135
  private static void SaveChangesToQualitySettings() {
@@ -1,6 +1,7 @@
1
1
  using UnityEngine;
2
2
  using UnityEditor;
3
3
  using System.Collections.Generic;
4
+ using System.Diagnostics;
4
5
  using System.IO;
5
6
  using Airship.Editor;
6
7
  using Code.Bootstrap;
@@ -38,6 +39,7 @@ public class AirshipSettingsProvider : SettingsProvider
38
39
  private bool showAutomaticEditorIntegrations = true;
39
40
  private bool showLuauOptions = true;
40
41
  private bool showNetworkOptions = true;
42
+ private bool showVoxelWorldOptions = false;
41
43
  private bool showBetaOptions = false;
42
44
 
43
45
  bool showGithubAccessToken = false;
@@ -185,7 +187,9 @@ public class AirshipSettingsProvider : SettingsProvider
185
187
 
186
188
  if (newTimeout != EditorIntegrationsConfig.instance.luauScriptTimeout) {
187
189
  EditorIntegrationsConfig.instance.luauScriptTimeout = newTimeout;
188
- LuauPlugin.SetScriptTimeoutDuration(newTimeout);
190
+ if (!Debugger.IsAttached) {
191
+ LuauPlugin.SetScriptTimeoutDuration(newTimeout);
192
+ }
189
193
  }
190
194
 
191
195
  if (GUI.changed) {
@@ -209,6 +213,22 @@ public class AirshipSettingsProvider : SettingsProvider
209
213
  }
210
214
  }
211
215
  EditorGUILayout.EndFoldoutHeaderGroup();
216
+
217
+ EditorGUILayout.Space();
218
+ showVoxelWorldOptions = EditorGUILayout.BeginFoldoutHeaderGroup(showVoxelWorldOptions, "Voxel World");
219
+ if (showVoxelWorldOptions) {
220
+ EditorGUILayout.HelpBox("Updating Server View Rendering requires you to restart multiplayer play mode window", MessageType.Warning);
221
+ VoxelWorldEditorConfig.instance.renderVoxelWorldInServerView = EditorGUILayout.Toggle(
222
+ new GUIContent(
223
+ "Server View Rendering",
224
+ "When enabled the Voxel World will be visible in dedicated server view. This is an editor only preference that results in worse performance (but can be useful for debugging)."
225
+ ), VoxelWorldEditorConfig.instance.renderVoxelWorldInServerView);
226
+
227
+ if (GUI.changed) {
228
+ VoxelWorldEditorConfig.instance.Modify();
229
+ }
230
+ }
231
+ EditorGUILayout.EndFoldoutHeaderGroup();
212
232
 
213
233
  // EditorGUILayout.Space();
214
234
  // showBetaOptions = EditorGUILayout.BeginFoldoutHeaderGroup(showBetaOptions, "Betas");
@@ -235,6 +255,12 @@ public class AirshipSettingsProvider : SettingsProvider
235
255
 
236
256
  [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
237
257
  private static void OnReload() {
238
- LuauPlugin.SetScriptTimeoutDuration(EditorIntegrationsConfig.instance.luauScriptTimeout);
258
+ if (Debugger.IsAttached) {
259
+ // If the debugger is attached, just feed in a large delay to effectively disable the timeout.
260
+ // In the future, we could adjust the plugin to take something like -1 to disable it.
261
+ LuauPlugin.SetScriptTimeoutDuration(86400);
262
+ } else {
263
+ LuauPlugin.SetScriptTimeoutDuration(EditorIntegrationsConfig.instance.luauScriptTimeout);
264
+ }
239
265
  }
240
266
  }
@@ -6,17 +6,18 @@ using UnityEngine.Scripting;
6
6
  namespace Code {
7
7
  [LuauAPI][Preserve]
8
8
  public static class AirshipConst {
9
- public const int playerVersion = 20;
9
+ public const int playerVersion = 23;
10
10
  public static readonly IReadOnlyList<string> playerFlags = new string[] {
11
11
  "SkipLoading",
12
12
  "LagCompCheckIdIsInt",
13
13
  "PlatformGearDownloadClassId",
14
+ "HasTransformMoveDirection", // True for versions that have access to CharacterMovement.TransformMoveDirection
14
15
  };
15
16
 
16
17
 
17
18
  /// <summary>
18
19
  /// The server will kick clients that have a playerVersion lower than this value.
19
20
  /// </summary>
20
- public const int minAcceptedPlayerVersionOnServer = 20;
21
+ public const int minAcceptedPlayerVersionOnServer = 23;
21
22
  }
22
23
  }
@@ -66,6 +66,9 @@ public class ServerBootstrap : MonoBehaviour
66
66
  private GameServer gameServer;
67
67
 
68
68
  [NonSerialized] public bool isServerReady = false;
69
+ /// <summary>
70
+ /// Can be fired multiple times.
71
+ /// </summary>
69
72
  public event Action OnStartLoadingGame;
70
73
  public event Action OnServerReady;
71
74
  public event Action OnStartupConfigReady;
@@ -373,6 +376,7 @@ public class ServerBootstrap : MonoBehaviour
373
376
  var request = UnityWebRequestProxyHelper.ApplyProxySettings(new UnityWebRequest(url));
374
377
  var gameConfigPath = Path.Combine(Application.persistentDataPath, "Games", startupConfig.GameBundleId, "gameConfig.json");
375
378
  request.downloadHandler = new DownloadHandlerFile(gameConfigPath);
379
+ request.timeout = 7;
376
380
  yield return request.SendWebRequest();
377
381
  if (request.result != UnityWebRequest.Result.Success) {
378
382
  Debug.LogError($"Failed to download gameConfig.json. url={url}, message={request.error}");
@@ -175,15 +175,25 @@ public class SystemRoot : Singleton<SystemRoot> {
175
175
  var sw = Stopwatch.StartNew();
176
176
 
177
177
  // Find packages we should UNLOAD
178
- List<string> unloadList = new();
178
+ HashSet<string> unloadList = new();
179
179
  foreach (var loadedPair in this.loadedAssetBundles) {
180
180
  if (forceUnloadAll) {
181
181
  unloadList.Add(loadedPair.Key);
182
182
  continue;
183
183
  }
184
+
184
185
  var packageToLoad = packages.Find(p => p.id.ToLower() == loadedPair.Value.airshipPackage.id.ToLower());
186
+ // Todo: we can not unload asset bundles if there is only a code change.
185
187
  if (packageToLoad == null || packageToLoad.assetVersion != loadedPair.Value.airshipPackage.assetVersion || packageToLoad.codeVersion != loadedPair.Value.airshipPackage.codeVersion) {
186
188
  unloadList.Add(loadedPair.Key);
189
+
190
+ // If a package changes, then we need to unload everything because other packages & the game may depend on it.
191
+ if (packageToLoad != null && packageToLoad.packageType == AirshipPackageType.Package) {
192
+ foreach (var loaded in loadedAssetBundles) {
193
+ unloadList.Add(loaded.Key);
194
+ }
195
+ break;
196
+ }
187
197
  }
188
198
  }
189
199
 
@@ -0,0 +1,26 @@
1
+ using Code.Bundles;
2
+ using TMPro;
3
+ using UnityEngine;
4
+
5
+ namespace Code.CoreUI.Components {
6
+ public class AirshipVersionOverlay : MonoBehaviour {
7
+ public TMP_Text versionText;
8
+
9
+ private void Start() {
10
+ #if !AIRSHIP_PLAYER
11
+ if (Application.isEditor) {
12
+ this.versionText.gameObject.SetActive(false);
13
+ return;
14
+ }
15
+ #endif
16
+
17
+ #if UNITY_IOS || UNITY_ANDROID
18
+ this.versionText.enabled = false;
19
+ return;
20
+ #endif
21
+
22
+ var hash = AirshipVersion.GetVersionHash();
23
+ this.versionText.text = Application.version + "-" + hash;
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: cc41e11900334dc284bc9b2dd63d0ed7
3
+ timeCreated: 1762977812
@@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
4
4
  using Mirror;
5
5
  using Code.Util;
6
6
  using Code.Zstd;
7
+ using UnityEngine;
7
8
 
8
9
  namespace Assets.Luau {
9
10
  [Serializable]
@@ -100,7 +101,7 @@ namespace Assets.Luau {
100
101
  NetworkWriterPool.Return(writer);
101
102
  NetworkWriterPool.Return(changedByteWriter);
102
103
 
103
- // Debug.Log($"Final diff is {bytes.Length} bytes");
104
+ // Debug.Log($"Final diff is {bytes.Length} bytes. Base data was {Data.Length}, new data was {other.Data.Length}. Change bytes: {changeBytes.Length}, Change data: {newByteValues.Length}");
104
105
  return bytes;
105
106
  }
106
107
 
@@ -258,11 +258,35 @@ public partial class LuauCore : MonoBehaviour {
258
258
  }
259
259
 
260
260
  #if UNITY_EDITOR
261
+ private PauseState _editorPauseState = PauseState.Unpaused;
262
+ private bool _appPaused = false;
263
+ private bool _pluginPaused = false;
264
+
265
+ private void OnApplicationOrEditorPauseChanged() {
266
+ var shouldPause = _appPaused || _editorPauseState == PauseState.Paused;
267
+ if (shouldPause == _pluginPaused) return;
268
+
269
+ _pluginPaused = shouldPause;
270
+ LuauPlugin.SetIsPaused(_pluginPaused);
271
+ }
272
+
261
273
  private void OnPauseStateChanged(PauseState state) {
262
- LuauPlugin.SetIsPaused(state == PauseState.Paused);
274
+ // Handle pauses in-editor triggered by the toolbar pause button
275
+ _editorPauseState = state;
276
+ OnApplicationOrEditorPauseChanged();
263
277
  }
264
278
  #endif
265
279
 
280
+ private void OnApplicationPause(bool pauseStatus) {
281
+ // Handle application pauses (e.g. when application loses focus on iOS)
282
+ #if UNITY_EDITOR
283
+ _appPaused = pauseStatus;
284
+ OnApplicationOrEditorPauseChanged();
285
+ #else
286
+ LuauPlugin.SetIsPaused(pauseStatus);
287
+ #endif
288
+ }
289
+
266
290
  private void Start() {
267
291
  Application.quitting += Quit;
268
292
  LuauPlugin.unityMainThreadId = Thread.CurrentThread.ManagedThreadId;
@@ -703,6 +703,9 @@ public partial class LuauCore : MonoBehaviour {
703
703
  }
704
704
  }
705
705
 
706
+ /// <summary>
707
+ /// Returns field value for a blittable object by directly accessing memory. Won't work for managed types.
708
+ /// </summary>
706
709
  private static unsafe T GetFieldValue<T>(object instance, FieldInfo fieldInfo) where T : unmanaged {
707
710
  var addr = UnsafeUtility.PinGCObjectAndGetAddress(instance, out ulong handle);
708
711
  try {
@@ -714,6 +717,12 @@ public partial class LuauCore : MonoBehaviour {
714
717
  }
715
718
 
716
719
  private static unsafe void SetFieldValue<T>(object instance, T value, FieldInfo fieldInfo) where T : unmanaged {
720
+ // If declaring type is not blittable just use reflection
721
+ if (!UnsafeUtility.IsBlittable(fieldInfo.DeclaringType)) {
722
+ fieldInfo.SetValue(instance, value);
723
+ return;
724
+ }
725
+
717
726
  if (fieldInfo.IsStatic) {
718
727
  // Not sure how to do non-alloc static field sets, so just use reflection for now
719
728
  // (these are relatively rare anyways)
@@ -1120,6 +1129,8 @@ public partial class LuauCore : MonoBehaviour {
1120
1129
  if (cacheData.memberInfo is not FieldInfo fieldInfo) throw new Exception("FastGetAndWriteValueField must be called with FieldInfo.");
1121
1130
 
1122
1131
  var fieldType = cacheData.memberType;
1132
+ // GetFieldValue only works reliably with blittable types
1133
+ if (!UnsafeUtility.IsBlittable(cacheData.objectType)) return false;
1123
1134
 
1124
1135
  if (fieldType == intType) {
1125
1136
  var intValue = GetFieldValue<int>(objectReference, fieldInfo);
@@ -350,13 +350,18 @@ public class GameObjectAPI : BaseLuaAPIClass {
350
350
  var gameObject = (GameObject)targetObject;
351
351
 
352
352
  Type objectType = LuauCore.CoreInstance.GetTypeFromString(typeName);
353
- if (objectType == null)
354
- {
353
+ if (objectType == null) {
355
354
  ThreadDataManager.Error(thread);
356
355
  Debug.LogError("Error: GetComponentsInChildren component type not found: " + typeName + " (consider registering it?)");
357
356
  return 0;
358
357
  }
359
- var results = gameObject.GetComponentsInChildren(objectType);
358
+
359
+ var includeInactive = false;
360
+ if (numParameters >= 2) {
361
+ includeInactive = LuauCore.GetParameterAsBool(1, numParameters, parameterDataPODTypes, parameterDataPtrs, parameterDataSizes, out _);
362
+ }
363
+
364
+ var results = gameObject.GetComponentsInChildren(objectType, includeInactive);
360
365
  LuauCore.WritePropertyToThread(thread, results, typeof(Component[]));
361
366
  return 1;
362
367
  }
@@ -380,7 +385,13 @@ public class GameObjectAPI : BaseLuaAPIClass {
380
385
  Debug.LogError("Error: GetComponentsInParent component type not found: " + typeName + " (consider registering it?)");
381
386
  return 0;
382
387
  }
383
- var results = gameObject.GetComponentsInParent(objectType);
388
+
389
+ var includeInactive = false;
390
+ if (numParameters >= 2) {
391
+ includeInactive = LuauCore.GetParameterAsBool(1, numParameters, parameterDataPODTypes, parameterDataPtrs, parameterDataSizes, out _);
392
+ }
393
+
394
+ var results = gameObject.GetComponentsInParent(objectType, includeInactive);
384
395
  LuauCore.WritePropertyToThread(thread, results, typeof(Component[]));
385
396
  return 1;
386
397
  }
@@ -135,7 +135,13 @@ public class TransformAPI : BaseLuaAPIClass {
135
135
  Debug.LogError("Error: GetComponentsInChildren component type not found: " + typeName + " (consider registering it?)");
136
136
  return 0;
137
137
  }
138
- var results = t.GetComponentsInChildren(objectType);
138
+
139
+ var includeInactive = false;
140
+ if (numParameters >= 2) {
141
+ includeInactive = LuauCore.GetParameterAsBool(1, numParameters, parameterDataPODTypes, parameterDataPtrs, parameterDataSizes, out _);
142
+ }
143
+
144
+ var results = t.GetComponentsInChildren(objectType, includeInactive);
139
145
  LuauCore.WritePropertyToThread(thread, results, typeof(Component[]));
140
146
  return 1;
141
147
  }
@@ -156,7 +162,13 @@ public class TransformAPI : BaseLuaAPIClass {
156
162
  Debug.LogError("Error: GetComponentsInParent component type not found: " + typeName + " (consider registering it?)");
157
163
  return 0;
158
164
  }
159
- var results = t.GetComponentsInParent(objectType);
165
+
166
+ var includeInactive = false;
167
+ if (numParameters >= 2) {
168
+ includeInactive = LuauCore.GetParameterAsBool(1, numParameters, parameterDataPODTypes, parameterDataPtrs, parameterDataSizes, out _);
169
+ }
170
+
171
+ var results = t.GetComponentsInParent(objectType, includeInactive);
160
172
  LuauCore.WritePropertyToThread(thread, results, typeof(Component[]));
161
173
  return 1;
162
174
  }
@@ -52,7 +52,15 @@ public class LuauHelper : Singleton<LuauHelper> {
52
52
  private void SetupUnityAPIClasses() {
53
53
  var assemblies = AppDomain.CurrentDomain.GetAssemblies();
54
54
  foreach (var assembly in assemblies) {
55
- if (!FastStartsWith(assembly.FullName, "Airship") && !FastStartsWith(assembly.FullName, "Easy")) {
55
+ var validAssembly = false;
56
+ foreach (var refName in assembly.GetReferencedAssemblies()) {
57
+ if (refName.Name == "LuauAPI") {
58
+ validAssembly = true;
59
+ break;
60
+ }
61
+ }
62
+
63
+ if (!validAssembly) {
56
64
  continue;
57
65
  }
58
66
 
@@ -1,6 +1,7 @@
1
1
  using System;
2
2
  using System.Collections.Generic;
3
3
  using Code.Luau;
4
+ using Code.Zstd;
4
5
  using Mirror;
5
6
  using UnityEngine;
6
7
  using UnityEngine.Scripting;
@@ -75,11 +76,16 @@ namespace Assets.Luau.Network {
75
76
 
76
77
  private void OnBroadcastFromClient(NetworkConnectionToClient conn, NetBroadcast msg) {
77
78
  // Runs on the server, when the client broadcasts a message
78
- if ((ulong)msg.Blob.DecompressedDataSize >= MaxBytesAtOnce) {
79
- Debug.LogWarning($"Dropping message from client connection {conn.connectionId} due to exceeding max data size.");
79
+ try {
80
+ if ((ulong)msg.Blob.DecompressedDataSize >= MaxBytesAtOnce) {
81
+ Debug.LogWarning(
82
+ $"Dropping message from client connection {conn.connectionId} due to exceeding max data size.");
83
+ return;
84
+ }
85
+ } catch (ZstdException) { // TODO: temporary code to discard Zstd exceptions
80
86
  return;
81
87
  }
82
-
88
+
83
89
  var now = Time.realtimeSinceStartup;
84
90
  if (!_throttle.TryGetValue(conn.connectionId, out var throttle)) {
85
91
  // If we don't have a throttle key, that means the client isn't connected anymore and we are processing an old message.