gg.easy.airship 0.1.2193 → 0.1.2194

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 (54) 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 +17 -0
  9. package/Runtime/Code/AirshipConst.cs +2 -2
  10. package/Runtime/Code/CoreUI/Components/AirshipVersionOverlay.cs +21 -0
  11. package/Runtime/Code/CoreUI/Components/AirshipVersionOverlay.cs.meta +3 -0
  12. package/Runtime/Code/Luau/LuauAssembly/BinaryBlob.cs +2 -1
  13. package/Runtime/Code/Luau/LuauCoreCallbacks.cs +5 -0
  14. package/Runtime/Code/LuauAPI/GameObjectAPI.cs +15 -4
  15. package/Runtime/Code/LuauAPI/TransformAPI.cs +14 -2
  16. package/Runtime/Code/LuauHelper/LuauHelper.cs +9 -1
  17. package/Runtime/Code/Network/Simulation/AirshipNetworkedObject.cs +1 -3
  18. package/Runtime/Code/Network/Simulation/AirshipSimulationManager.cs +11 -10
  19. package/Runtime/Code/Network/Simulation/History.cs +3 -3
  20. package/Runtime/Code/Network/StateSystem/AirshipNetworkedStateManager.cs +21 -15
  21. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestMovementInputDiff.cs +7 -0
  22. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestMovementInputDiff.cs.meta +3 -0
  23. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestMovementInputGroup.cs +16 -0
  24. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestMovementInputGroup.cs.meta +3 -0
  25. package/Runtime/Code/Network/StateSystem/Implementations/TestMovementSystem/TestNetworkedStateManager.cs +7 -5
  26. package/Runtime/Code/Network/StateSystem/Structures/InputCommand.cs +9 -0
  27. package/Runtime/Code/Network/StateSystem/Structures/InputCommandDiff.cs +13 -0
  28. package/Runtime/Code/Network/StateSystem/Structures/InputCommandDiff.cs.meta +3 -0
  29. package/Runtime/Code/Network/StateSystem/Structures/InputCommandGroup.cs +43 -0
  30. package/Runtime/Code/Network/StateSystem/Structures/InputCommandGroup.cs.meta +3 -0
  31. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterMovement.cs +68 -167
  32. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterNetworkedStateManager.cs +5 -6
  33. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterPhysics.cs +2 -2
  34. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputData.cs +113 -2
  35. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputDiff.cs +56 -0
  36. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputDiff.cs.meta +3 -0
  37. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputGroup.cs +27 -0
  38. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterInputGroup.cs.meta +3 -0
  39. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterSnapshotData.cs +30 -41
  40. package/Runtime/Code/VoxelWorld/Resources/VoxelWorldMatURP.mat +3 -3
  41. package/Runtime/Code/VoxelWorld/VoxelWorld.cs +41 -24
  42. package/Runtime/Code/VoxelWorld/VoxelWorldChunk.cs +4 -1
  43. package/Runtime/Code/VoxelWorld/VoxelWorldEditorConfig.cs +13 -0
  44. package/Runtime/Code/VoxelWorld/VoxelWorldEditorConfig.cs.meta +3 -0
  45. package/Runtime/Code/VoxelWorld/VoxelWorldNetworker.cs +2 -0
  46. package/Runtime/Scenes/CoreScene.unity +261 -648
  47. package/ThirdParty/UiRoundedCorners/ImageWithIndependentRoundedCorners.cs +1 -0
  48. package/ThirdParty/UiRoundedCorners/ImageWithRoundedCorners.cs +1 -0
  49. package/URP/AirshipLowestURPAsset_Renderer.asset +1 -1
  50. package/URP/AirshipMobileURPAsset.asset +2 -0
  51. package/URP/AirshipMobileURPAsset_Renderer.asset +3 -3
  52. package/URP/AirshipURPAsset.asset +3 -1
  53. package/URP/AirshipURPAsset_Renderer.asset +3 -3
  54. 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() {
@@ -38,6 +38,7 @@ public class AirshipSettingsProvider : SettingsProvider
38
38
  private bool showAutomaticEditorIntegrations = true;
39
39
  private bool showLuauOptions = true;
40
40
  private bool showNetworkOptions = true;
41
+ private bool showVoxelWorldOptions = false;
41
42
  private bool showBetaOptions = false;
42
43
 
43
44
  bool showGithubAccessToken = false;
@@ -209,6 +210,22 @@ public class AirshipSettingsProvider : SettingsProvider
209
210
  }
210
211
  }
211
212
  EditorGUILayout.EndFoldoutHeaderGroup();
213
+
214
+ EditorGUILayout.Space();
215
+ showVoxelWorldOptions = EditorGUILayout.BeginFoldoutHeaderGroup(showVoxelWorldOptions, "Voxel World");
216
+ if (showVoxelWorldOptions) {
217
+ EditorGUILayout.HelpBox("Updating Server View Rendering requires you to restart multiplayer play mode window", MessageType.Warning);
218
+ VoxelWorldEditorConfig.instance.renderVoxelWorldInServerView = EditorGUILayout.Toggle(
219
+ new GUIContent(
220
+ "Server View Rendering",
221
+ "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)."
222
+ ), VoxelWorldEditorConfig.instance.renderVoxelWorldInServerView);
223
+
224
+ if (GUI.changed) {
225
+ VoxelWorldEditorConfig.instance.Modify();
226
+ }
227
+ }
228
+ EditorGUILayout.EndFoldoutHeaderGroup();
212
229
 
213
230
  // EditorGUILayout.Space();
214
231
  // showBetaOptions = EditorGUILayout.BeginFoldoutHeaderGroup(showBetaOptions, "Betas");
@@ -6,7 +6,7 @@ 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 = 21;
10
10
  public static readonly IReadOnlyList<string> playerFlags = new string[] {
11
11
  "SkipLoading",
12
12
  "LagCompCheckIdIsInt",
@@ -17,6 +17,6 @@ namespace Code {
17
17
  /// <summary>
18
18
  /// The server will kick clients that have a playerVersion lower than this value.
19
19
  /// </summary>
20
- public const int minAcceptedPlayerVersionOnServer = 20;
20
+ public const int minAcceptedPlayerVersionOnServer = 21;
21
21
  }
22
22
  }
@@ -0,0 +1,21 @@
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
+ var hash = AirshipVersion.GetVersionHash();
18
+ this.versionText.text = Application.version + "-" + hash;
19
+ }
20
+ }
21
+ }
@@ -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
 
@@ -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 {
@@ -1120,6 +1123,8 @@ public partial class LuauCore : MonoBehaviour {
1120
1123
  if (cacheData.memberInfo is not FieldInfo fieldInfo) throw new Exception("FastGetAndWriteValueField must be called with FieldInfo.");
1121
1124
 
1122
1125
  var fieldType = cacheData.memberType;
1126
+ // GetFieldValue only works reliably with blittable types
1127
+ if (!UnsafeUtility.IsBlittable(cacheData.objectType)) return false;
1123
1128
 
1124
1129
  if (fieldType == intType) {
1125
1130
  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
 
@@ -78,9 +78,7 @@ namespace Code.Network.Simulation
78
78
 
79
79
  private void LagCompensationCheck(int clientId, int tick, double time, double latency, double bufferTime)
80
80
  {
81
- var commandBufferTime = (NetworkServer.sendInterval * (NetworkClient.bufferTimeMultiplier / 2f));
82
-
83
- var totalBuffer = (latency * 2) + bufferTime + commandBufferTime;
81
+ var totalBuffer = (latency * 2) + bufferTime;
84
82
  var lagCompensatedTime = time - (totalBuffer + bufferAdjustment);
85
83
  var lagCompensatedTick = AirshipSimulationManager.Instance.GetNearestTickForUnscaledTime(lagCompensatedTime);
86
84
  this.SetSnapshot(lagCompensatedTick);
@@ -205,13 +205,7 @@ namespace Code.Network.Simulation
205
205
 
206
206
  // Only resimulate once. Go back to the farthest back time that was requested.
207
207
  if (resimBackTo != tick) this.PerformResimulation(resimBackTo);
208
-
209
- // Perform the standard tick behavior
210
- OnTick?.Invoke(tick, time, false);
211
- // Debug.Log($"Simulate call. Main tick {tick}");
212
- Physics.Simulate(Time.fixedDeltaTime);
213
- OnCaptureSnapshot?.Invoke(tick, time, false);
214
-
208
+
215
209
  // Process any lag compensation requests now that we have completed the ticking and snapshot creation
216
210
  // Note: This process is placed after snapshot processing so that changes made to physics (like an impulse)
217
211
  // are processed on the _next_ tick. This is safe because the server never resimulates.
@@ -224,7 +218,7 @@ namespace Code.Network.Simulation
224
218
  // Debug.LogWarning("Server lag compensation rolling back for client " + entry.Key.connectionId);
225
219
  // commandBufferTime is the additional time we queue commands locally on the server before processing them
226
220
  var commandBufferTime = (NetworkServer.sendInterval * (entry.Key.bufferTimeMultiplier / 2f));
227
- OnLagCompensationCheck?.Invoke(entry.Key.connectionId, tick, time, entry.Key.rtt / 2f, entry.Key.bufferTime + commandBufferTime);
221
+ OnLagCompensationCheck?.Invoke(entry.Key.connectionId, previousTicks[^1], previousTimes[^1], entry.Key.rtt / 2f, entry.Key.bufferTime + commandBufferTime);
228
222
 
229
223
  var requests = entry.Value;
230
224
  for (var i = 0; i < requests.Count; i++) {
@@ -240,9 +234,10 @@ namespace Code.Network.Simulation
240
234
  // If we processed lag compensation, we have some additional work to do
241
235
  if (processedLagCompensation)
242
236
  {
243
- // Debug.LogWarning("Server completed " + this.lagCompensationRequests.Count + " lag compensation requests. Resetting to current tick (" + time + ") and finalizing.");
237
+ // Debug.LogWarning("Server completed " + this.lagCompensationRequests.Count + " lag compensation requests. Resetting to current tick (" + previousTimes[^1] + ") and finalizing.");
244
238
  // Reset back to the server view of the world at the current time.
245
- OnSetSnapshot?.Invoke(tick);
239
+ OnSetSnapshot?.Invoke(previousTicks[^1]);
240
+ Physics.SyncTransforms();
246
241
  // Invoke all of the callbacks for modifying physics that should be applied in the next tick.
247
242
  foreach (var entry in this.lagCompensationRequests)
248
243
  {
@@ -261,6 +256,12 @@ namespace Code.Network.Simulation
261
256
  this.lagCompensationRequests.Clear();
262
257
  }
263
258
 
259
+ // Perform the standard tick behavior
260
+ OnTick?.Invoke(tick, time, false);
261
+ // Debug.Log($"Simulate call. Main tick {tick}");
262
+ Physics.Simulate(Time.fixedDeltaTime);
263
+ OnCaptureSnapshot?.Invoke(tick, time, false);
264
+
264
265
  // Add our completed tick time into our history
265
266
  this.previousTicks.Add(tick);
266
267
  this.previousTimes.Add(time);
@@ -210,7 +210,7 @@ namespace Code.Network.Simulation
210
210
  */
211
211
  public T[] GetAllAfter(int tick)
212
212
  {
213
- if (this.history.Keys.Count == 0 || tick > this.history.Keys[^1])
213
+ if (this.history.Keys.Count == 0 || tick >= this.history.Keys[^1])
214
214
  {
215
215
  return new T[] {};
216
216
  }
@@ -219,7 +219,7 @@ namespace Code.Network.Simulation
219
219
  // Iterate in reverse since our return values will likely include the end
220
220
  for (var i = this.history.Count - 1; i >= 0; i--)
221
221
  {
222
- if (this.history.Keys[i] < tick)
222
+ if (this.history.Keys[i] <= tick)
223
223
  {
224
224
  after.Reverse();
225
225
  return after.ToArray();
@@ -270,4 +270,4 @@ namespace Code.Network.Simulation
270
270
  }
271
271
  }
272
272
  }
273
- }
273
+ }
@@ -54,8 +54,10 @@ namespace Code.Network.StateSystem
54
54
 
55
55
  private double lastServerSend = 0;
56
56
 
57
- // The local time contained in the last data sent. This is used to know which data we have already sent to the server
57
+ // The local tick of the most recent data that was sent to the server.
58
58
  private int clientLastSentLocalTick = 0;
59
+ // The local tick of the last data that was sent the the server a second time.
60
+ private int clientLastResentLocalTick = 0;
59
61
 
60
62
  // Server processing for commands
61
63
  private Input lastProcessedCommand;
@@ -126,10 +128,10 @@ namespace Code.Network.StateSystem
126
128
  protected Action<Diff> OnClientReceiveDiff;
127
129
  protected Action<int> OnServerReceiveFullSnapshotRequest;
128
130
  protected Action<State> OnServerReceiveSnapshot;
129
- protected Action<Input> OnServerReceiveInput;
131
+ protected Action<Input[]> OnServerReceiveInput;
130
132
 
131
133
  // Functions to be implemented by subclass that perform networking actions
132
- public abstract void SendClientInputToServer(Input input);
134
+ public abstract void SendClientInputToServer(Input[] input);
133
135
  public abstract void SendClientSnapshotToServer(State snapshot);
134
136
 
135
137
  /// <summary>
@@ -253,27 +255,27 @@ namespace Code.Network.StateSystem
253
255
  // We will sometimes resend unconfirmed commands. The server should ignore these if
254
256
  // it has them already.
255
257
  var commands =
256
- this.inputHistory.GetAllAfter((int)Math.Max(0,
257
- (clientLastSentLocalTick - (NetworkClient.sendInterval / Time.fixedUnscaledDeltaTime))));
258
+ this.inputHistory.GetAllAfter((int)Math.Max(0,clientLastResentLocalTick)); // Send all inputs that haven't been sent as well as ones that have been sent only once
258
259
  if (commands.Length > 0) {
259
- this.clientLastSentLocalTick = this.inputHistory.Keys[^1];
260
+ this.clientLastResentLocalTick = this.clientLastSentLocalTick; // Store the last tick that was resent
261
+ this.clientLastSentLocalTick = this.inputHistory.Keys[^1]; // Store which tick was sent
262
+ this.SendClientInputToServer(commands);
260
263
  }
261
264
 
262
265
  // print($"Sending {commands.Length} cmds to the server");
263
266
 
264
- // We make multiple calls so that Mirror can batch the commands efficiently.
265
- foreach (var command in commands) {
266
- this.SendClientInputToServer(command);
267
- }
267
+ // // We make multiple calls so that Mirror can batch the commands efficiently.
268
+ // foreach (var command in commands) {
269
+ // this.SendClientInputToServer(command);
270
+ // }
268
271
  }
269
272
 
270
273
  // We are an authoritative client and should send our latest state
271
274
  if (isClient && isOwned && !serverAuth) {
272
275
  if (this.stateHistory.Keys.Count == 0) return;
273
- var states = this.stateHistory.GetAllAfter((int)Math.Max(0, (this.clientLastSentLocalTick -
274
- (NetworkClient.sendInterval /
275
- Time.fixedUnscaledDeltaTime))));
276
+ var states = this.stateHistory.GetAllAfter((int)Math.Max(0, clientLastResentLocalTick));
276
277
  if (states.Length > 0) {
278
+ this.clientLastResentLocalTick = this.clientLastSentLocalTick;
277
279
  this.clientLastSentLocalTick = this.stateHistory.Keys[^1];
278
280
  }
279
281
 
@@ -1218,9 +1220,13 @@ namespace Code.Network.StateSystem
1218
1220
  this.serverCommandBuffer.Add(command.commandNumber, command);
1219
1221
  }
1220
1222
 
1221
- private void ServerReceiveInputCommand(Input command)
1223
+ private void ServerReceiveInputCommand(Input[] commands)
1222
1224
  {
1223
- ProcessClientInputOnServer(command);
1225
+ foreach (var command in commands)
1226
+ {
1227
+ ProcessClientInputOnServer(command);
1228
+ }
1229
+
1224
1230
  }
1225
1231
 
1226
1232
  private void ServerReceiveSnapshot(State snapshot)