gg.easy.airship 0.1.2163 → 0.1.2165

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 (33) hide show
  1. package/.editorconfig +9 -0
  2. package/Runtime/Code/AirshipConst.cs +2 -2
  3. package/Runtime/Code/Analytics/ClientFolderUploader.cs +176 -0
  4. package/Runtime/Code/Analytics/ClientFolderUploader.cs.meta +2 -0
  5. package/Runtime/Code/Bootstrap/ClientBootstrap.cs +4 -0
  6. package/Runtime/Code/Bundles/AssetBridge.cs +1 -1
  7. package/Runtime/Code/Bundles/SystemRoot.cs +20 -15
  8. package/Runtime/Code/Luau/LuauCoreReflection.cs +1 -1
  9. package/Runtime/Code/Luau/ReflectionList.cs +1 -0
  10. package/Runtime/Code/LuauAPI/FrameTimingManagerAPI.cs +22 -2
  11. package/Runtime/Code/Network/StateSystem/AirshipNetworkedStateManager.cs +30 -12
  12. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterMovement.cs +127 -31
  13. package/Runtime/Code/Player/PlayerInfo.cs +2 -2
  14. package/Runtime/Code/Player/PlayerManagerBridge.cs +1 -1
  15. package/Runtime/Code/Quality/QualityManager.cs +143 -0
  16. package/Runtime/Code/Quality/QualityManager.cs.meta +3 -0
  17. package/Runtime/Code/Quality.meta +3 -0
  18. package/Runtime/Code/Steam/SteamLuauAPI.cs +34 -31
  19. package/Runtime/Code/VoiceChat/AirshipUniVoiceNetwork.cs +7 -0
  20. package/Runtime/Code/VoxelWorld/Resources/SampleDerivative.hlsl +7 -0
  21. package/Runtime/Code/VoxelWorld/Resources/SampleDerivative.hlsl.meta +7 -0
  22. package/Runtime/Code/VoxelWorld/Resources/VoxelWorldAtlasURP.shadergraph +1442 -161
  23. package/Runtime/Code/VoxelWorld/Resources/VoxelWorldMatURP.mat +2 -2
  24. package/Runtime/Code/VoxelWorld/TexturePacker.cs +31 -24
  25. package/Runtime/Code/VoxelWorld/VoxelBlocks.cs +4 -4
  26. package/Runtime/DevConsole/Resources/Prefabs/FAB_DevConsole.Instance.prefab +305 -1
  27. package/Runtime/Scenes/CoreScene.unity +246 -141
  28. package/ThirdParty/Graphy - Ultimate Stats Monitor/Runtime/Timings/G_TimingsGraph.cs +7 -6
  29. package/package.json +1 -2
  30. package/ThirdParty/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph +0 -12074
  31. package/ThirdParty/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta +0 -10
  32. package/ThirdParty/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph +0 -11759
  33. package/ThirdParty/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta +0 -10
package/.editorconfig ADDED
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*.cs]
4
+ csharp_new_line_before_open_brace = none
5
+ csharp_new_line_before_else = false
6
+ csharp_new_line_before_catch = false
7
+ csharp_new_line_before_finally = false
8
+ csharp_new_line_before_members_in_object_initializers = false
9
+ csharp_new_line_before_members_in_anonymous_types = false
@@ -1,11 +1,11 @@
1
1
  // ReSharper disable InconsistentNaming
2
2
  namespace Code {
3
3
  public static class AirshipConst {
4
- public const int playerVersion = 12;
4
+ public const int playerVersion = 13;
5
5
 
6
6
  /// <summary>
7
7
  /// The server will kick clients that have a playerVersion lower than this value.
8
8
  /// </summary>
9
- public const int minAcceptedPlayerVersionOnServer = 12;
9
+ public const int minAcceptedPlayerVersionOnServer = 13;
10
10
  }
11
11
  }
@@ -0,0 +1,176 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.IO;
4
+ using System.IO.Compression;
5
+ using System.Threading.Tasks;
6
+ using Code.Http.Internal;
7
+ using Code.Http.Public;
8
+ using Code.Platform.Shared;
9
+ using Proyecto26;
10
+ using UnityEngine;
11
+
12
+ namespace Code.Analytics {
13
+ [Serializable]
14
+ public class PostArtifactResponse {
15
+ public string id;
16
+ public string url;
17
+ }
18
+
19
+ [Serializable]
20
+ public class RequestBody {
21
+ public string type;
22
+ public string name;
23
+ public string contentType;
24
+ public long contentLength;
25
+ }
26
+
27
+ public class ClientFolderUploader : MonoBehaviour {
28
+
29
+ // Start in the past otherwise they can't do this for the first 10 seconds since time starts at 0.
30
+ private float timeOfLastUpload = -10;
31
+
32
+ public void ButtonClick() {
33
+ if (Time.unscaledTime - timeOfLastUpload < 10) {
34
+ Debug.LogWarning("[ClientFolderUploader] Upload already in progress or too soon after last upload");
35
+ return;
36
+ }
37
+ timeOfLastUpload = Time.unscaledTime;
38
+
39
+ _ = UploadAsync();
40
+ }
41
+
42
+ private async Task UploadAsync() {
43
+ try {
44
+ await Upload();
45
+ Debug.Log("[ClientFolderUploader] Upload completed successfully");
46
+ } catch (Exception ex) {
47
+ Debug.LogError($"[ClientFolderUploader] Upload failed: {ex.Message}");
48
+ }
49
+ }
50
+
51
+ public async Task Upload() {
52
+ try {
53
+ var path = Path.GetDirectoryName(Application.consoleLogPath);
54
+
55
+ var zipPath = Path.Combine(Application.temporaryCachePath, "logs.zip");
56
+ if (File.Exists(zipPath)) {
57
+ File.Delete(zipPath);
58
+ }
59
+
60
+ var playerLogFile = Path.Combine(path, "Player.log");
61
+ var tempCurPlayerLogFile = Path.Combine(path, "Player-cur.log");
62
+ var playerPrevLogFile = Path.Combine(path, "Player-prev.log");
63
+ var editorLogFile = Path.Combine(path, "Editor.log");
64
+ var tempCurEditorLogFile = Path.Combine(path, "Editor-cur.log");
65
+ var editorPrevLogFile = Path.Combine(path, "Editor-prev.log");
66
+
67
+ var logMessages = new List<string>();
68
+
69
+ Action printDebugLines = () => {
70
+ foreach (var message in logMessages) {
71
+ Debug.Log(message);
72
+ }
73
+ logMessages.Clear();
74
+ };
75
+
76
+ var cleanupFiles = new List<string>() {
77
+ zipPath,
78
+ };
79
+
80
+ Debug.Log("[ClientFolderUploader] Creating zip archive");
81
+ try {
82
+ if (File.Exists(zipPath)) {
83
+ File.Delete(zipPath);
84
+ }
85
+ using (var archive = ZipFile.Open(zipPath, ZipArchiveMode.Create)) {
86
+ var fileExists = false;
87
+ if (File.Exists(playerLogFile)) {
88
+ fileExists = true;
89
+ File.Copy(playerLogFile, tempCurPlayerLogFile, true);
90
+ logMessages.Add("[ClientFolderUploader] Adding Player.log");
91
+ archive.CreateEntryFromFile(tempCurPlayerLogFile, "Player.log");
92
+ cleanupFiles.Add(tempCurPlayerLogFile);
93
+ }
94
+
95
+ if (File.Exists(playerPrevLogFile)) {
96
+ fileExists = true;
97
+ logMessages.Add("[ClientFolderUploader] Adding Player-prev.log");
98
+ archive.CreateEntryFromFile(playerPrevLogFile, "Player-prev.log");
99
+ }
100
+
101
+ if (File.Exists(editorLogFile)) {
102
+ fileExists = true;
103
+ File.Copy(editorLogFile, tempCurEditorLogFile, true);
104
+ logMessages.Add("[ClientFolderUploader] Adding Editor.log");
105
+ archive.CreateEntryFromFile(tempCurEditorLogFile, "Editor.log");
106
+ cleanupFiles.Add(tempCurEditorLogFile);
107
+ }
108
+
109
+ if (File.Exists(editorPrevLogFile)) {
110
+ fileExists = true;
111
+ logMessages.Add("[ClientFolderUploader] Adding Editor-prev.log");
112
+ archive.CreateEntryFromFile(editorPrevLogFile, "Editor-prev.log");
113
+ }
114
+
115
+ if (!fileExists) {
116
+ return;
117
+ }
118
+ }
119
+ } catch (Exception ex) {
120
+ printDebugLines();
121
+ Debug.LogError($"[ClientFolderUploader] Zip creation failed: {ex.Message}");
122
+ throw;
123
+ }
124
+
125
+ printDebugLines();
126
+
127
+ var contentType = "application/zip";
128
+ var contentLength = new FileInfo(zipPath).Length;
129
+
130
+ var body = new RequestBody {
131
+ type = "CLIENT_DEBUG_ARCHIVE",
132
+ name = "PlayerLogs.zip",
133
+ contentType = contentType,
134
+ contentLength = contentLength,
135
+ };
136
+
137
+ Debug.Log("[ClientFolderUploader] Creating artifact");
138
+ var url = $"{AirshipPlatformUrl.contentService}/artifacts/platform/signed-url";
139
+
140
+ Http.HttpResponse res;
141
+ if (String.IsNullOrEmpty(InternalHttpManager.authToken)) {
142
+ res = await HttpManager.PostAsync(url, JsonUtility.ToJson(body));
143
+ } else {
144
+ res = await InternalHttpManager.PostAsync(url, JsonUtility.ToJson(body));
145
+ }
146
+
147
+ if (res.statusCode < 200 || res.statusCode >= 300) {
148
+ Debug.LogError($"[ClientFolderUploader] Error response from server: {res.statusCode} - {res.error}");
149
+ throw new Exception($"Failed to get signed URL: {res.error}");
150
+ }
151
+
152
+ var response = JsonUtility.FromJson<PostArtifactResponse>(res.data);
153
+
154
+ Debug.Log("[ClientFolderUploader] Uploading file");
155
+ await HttpManager.PutAsync(new RequestHelper() {
156
+ Uri = response.url,
157
+ BodyRaw = File.ReadAllBytes(zipPath),
158
+ Headers = new System.Collections.Generic.Dictionary<string, string>
159
+ {
160
+ { "Content-Type", contentType },
161
+ },
162
+ }, "");
163
+
164
+ Debug.Log("[ClientFolderUploader] Deleting temporary files");
165
+ foreach (var file in cleanupFiles) {
166
+ if (File.Exists(file)) {
167
+ File.Delete(file);
168
+ }
169
+ }
170
+ } catch (Exception ex) {
171
+ Debug.LogError($"[ClientFolderUploader] Error during upload process: {ex.Message}");
172
+ throw;
173
+ }
174
+ }
175
+ }
176
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 474c8118d514c47d2b470bdd6dd04d84
@@ -8,7 +8,11 @@ public class ClientBootstrap : MonoBehaviour
8
8
  private void Start()
9
9
  {
10
10
  if (RunCore.IsClient()) {
11
+ #if UNITY_STANDALONE_OSX
12
+ Application.targetFrameRate = -1;
13
+ #else
11
14
  Application.targetFrameRate = (int)Math.Ceiling(Screen.currentResolution.refreshRateRatio.value);
15
+ #endif
12
16
  Application.logMessageReceived += AnalyticsRecorder.RecordLogMessageToAnalytics;
13
17
  }
14
18
  }
@@ -259,7 +259,7 @@ public class AssetBridge : IAssetBridge
259
259
  #endif
260
260
 
261
261
  if (printErrorOnFail) {
262
- Debug.LogError("AssetBundle file not found: " + path + " (No asset bundle understood this path - is this asset bundle loaded?)");
262
+ Debug.LogError($"Failed to load asset at path \"{path}\". Are you sure it exists?");
263
263
  }
264
264
  return null;
265
265
  }
@@ -35,6 +35,7 @@ public class SystemRoot : Singleton<SystemRoot> {
35
35
  public List<AssetBundleCreateRequest> extraBundleLoadRequests = new();
36
36
  public static bool startedLoadingExtraBundle = false;
37
37
  public static bool preWarmedCoreShaders = false;
38
+ private static bool disableCoreMaterialsBundle = false;
38
39
  public AssetBundle coreMaterialsAssetBundle;
39
40
  private bool loadInProgress = false;
40
41
 
@@ -105,16 +106,18 @@ public class SystemRoot : Singleton<SystemRoot> {
105
106
  Debug.Log($"Loaded CoreMaterials bundle in {st.ElapsedMilliseconds} ms.");
106
107
  }
107
108
  #else
108
- if (File.Exists(path)) {
109
- Debug.Log($"Loading CoreMaterials... ({path})");
110
- var st = Stopwatch.StartNew();
111
- var ao = AssetBundle.LoadFromFileAsync(path);
112
- this.extraBundleLoadRequests.Add(ao);
113
- await ao;
114
- this.coreMaterialsAssetBundle = ao.assetBundle;
115
- Debug.Log($"Loaded CoreMaterials bundle in {st.ElapsedMilliseconds} ms.");
116
- } else {
117
- Debug.LogWarning($"CoreMaterials path not found ({path})");
109
+ if (!disableCoreMaterialsBundle) {
110
+ if (File.Exists(path)) {
111
+ Debug.Log($"Loading CoreMaterials... ({path})");
112
+ var st = Stopwatch.StartNew();
113
+ var ao = AssetBundle.LoadFromFileAsync(path);
114
+ this.extraBundleLoadRequests.Add(ao);
115
+ await ao;
116
+ this.coreMaterialsAssetBundle = ao.assetBundle;
117
+ Debug.Log($"Loaded CoreMaterials bundle in {st.ElapsedMilliseconds} ms.");
118
+ } else {
119
+ Debug.LogWarning($"CoreMaterials path not found ({path})");
120
+ }
118
121
  }
119
122
  #endif
120
123
  }
@@ -342,11 +345,13 @@ public class SystemRoot : Singleton<SystemRoot> {
342
345
  yield return this.WaitAll(loadLists[0].ToArray());
343
346
  Debug.Log("Loading game...");
344
347
  yield return this.WaitAll(loadLists[1].ToArray());
345
-
346
- foreach (var ao in this.extraBundleLoadRequests) {
347
- if (!ao.isDone) {
348
- Debug.Log("Waiting for shipped asset bundles to load...");
349
- yield return ao;
348
+
349
+ if (!disableCoreMaterialsBundle) {
350
+ foreach (var ao in this.extraBundleLoadRequests) {
351
+ if (!ao.isDone) {
352
+ Debug.Log("Waiting for shipped asset bundles to load...");
353
+ yield return ao;
354
+ }
350
355
  }
351
356
  }
352
357
 
@@ -420,7 +420,7 @@ public partial class LuauCore : MonoBehaviour
420
420
  LuauPlugin.LuauPushValueToThread(thread, (int)PODTYPE.POD_DOUBLE, new IntPtr(value: &value), 0);
421
421
  }
422
422
 
423
- private static bool WriteArrayToThread(IntPtr thread, IEnumerable array, Type t, int knownSize = 0) {
423
+ public static bool WriteArrayToThread(IntPtr thread, IEnumerable array, Type t, int knownSize = 0) {
424
424
  LuauPluginRaw.NewTable(thread, knownSize);
425
425
 
426
426
  var i = 0;
@@ -187,6 +187,7 @@ namespace Luau {
187
187
  [typeof(MeshFilter)] = LuauContextAll,
188
188
  [typeof(Sprite)] = LuauContextAll,
189
189
  [typeof(DecalProjector)] = LuauContextAll,
190
+ [typeof(LODGroup)] = LuauContextAll,
190
191
  //Spline
191
192
  [typeof(Spline)] = LuauContextAll,
192
193
  [typeof(BezierCurve)] = LuauContextAll,
@@ -3,8 +3,28 @@ using UnityEngine;
3
3
 
4
4
  [LuauAPI]
5
5
  public class FrameTimingManagerAPI : BaseLuaAPIClass {
6
- public override Type GetAPIType()
7
- {
6
+ public override Type GetAPIType() {
8
7
  return typeof(UnityEngine.FrameTimingManager);
9
8
  }
9
+
10
+ public override int OverrideStaticMethod(LuauContext context, IntPtr thread, string methodName, int numParameters,
11
+ ArraySegment<int> parameterDataPODTypes, ArraySegment<IntPtr> parameterDataPtrs,
12
+ ArraySegment<int> parameterDataSizes) {
13
+ if (methodName is "GetLatestTimings") {
14
+ if (numParameters != 1) throw new ArgumentException("GetLatestTimings expects 1 parameter.");
15
+
16
+ var numTimings = (uint) LuauCore.GetParameterAsInt(0, numParameters, parameterDataPODTypes, parameterDataPtrs,
17
+ parameterDataSizes);
18
+
19
+ // Arbitrary limit to avoid huge allocations / requests
20
+ if (numTimings > 1000) throw new ArgumentException("Requested too many frames (>1000) from GetLatestTimings.");
21
+
22
+ // This function will alloc -- we could look to in the future support a non-alloc setup
23
+ var timings = new FrameTiming[numTimings];
24
+ var fetchedResults = FrameTimingManager.GetLatestTimings(numTimings, timings);
25
+ LuauCore.WriteArrayToThread(thread, timings, typeof(FrameTiming), (int) fetchedResults);
26
+ return 1;
27
+ }
28
+ return -1;
29
+ }
10
30
  }
@@ -76,6 +76,8 @@ namespace Code.Network.StateSystem
76
76
  // Non-auth server command tracking
77
77
  // Note: we also re-use some of the above command buffer fields
78
78
  private SortedList<int, State> serverReceivedStateBuffer = new SortedList<int, State>();
79
+ // Last observed state from OnTick when running as a non-auth server.
80
+ private State serverLastObservedState;
79
81
 
80
82
  // Client processing for input prediction
81
83
  private State clientLastConfirmedState;
@@ -224,6 +226,12 @@ namespace Code.Network.StateSystem
224
226
  simManager.OnSetSnapshot -= this.OnSetSnapshot;
225
227
  simManager.OnCaptureSnapshot -= this.OnCaptureSnapshot;
226
228
  simManager.OnLagCompensationCheck -= this.OnLagCompensationCheck;
229
+
230
+ this.OnClientReceiveSnapshot -= ClientReceiveSnapshot;
231
+ this.OnClientReceiveDiff -= ClientReceiveDiff;
232
+ this.OnServerReceiveSnapshot -= ServerReceiveSnapshot;
233
+ this.OnServerReceiveInput -= ServerReceiveInputCommand;
234
+ this.OnServerReceiveFullSnapshotRequest -= ServerReceiveFullSnapshotRequest;
227
235
  }
228
236
 
229
237
  private void SendNetworkMessages() {
@@ -810,20 +818,30 @@ namespace Code.Network.StateSystem
810
818
  // not a shared timeline.
811
819
  latestState.tick = tick;
812
820
  latestState.time = time;
821
+ this.serverLastObservedState = latestState;
813
822
  // Use this as the current state for the server
814
823
  this.stateSystem.SetCurrentState(latestState);
815
824
  // Since it's new, update our server interpolation functions
816
- this.stateSystem.InterpolateReachedState(latestState);
817
- // Add the state to our history as we would in a authoritative setup
818
- this.stateHistory.Set(tick, latestState);
825
+ this.stateSystem.InterpolateReachedState(latestState);
819
826
  }
820
827
  }
821
828
 
822
- public void NonAuthServerCaptureSnapshot(int tick, double time, bool replay)
823
- {
824
- // Non server auth will accept the client auth as the official possition. No need to capture
825
- // the state after the physics tick as the position that was pulled from the buffer in OnTick
826
- // was already added to the state timeline as the official position.
829
+ public void NonAuthServerCaptureSnapshot(int tick, double time, bool replay) {
830
+ if (this.serverLastObservedState != null) {
831
+ // Non server auth will accept the client auth as the official position. No need to get
832
+ // the state after the physics tick as the position that was pulled from the buffer in OnTick
833
+ // is the official position.
834
+ var authState = this.serverLastObservedState.Clone() as State;
835
+ authState.tick = tick;
836
+ authState.time = time;
837
+ this.stateHistory.Set(tick, authState);
838
+ }
839
+ else {
840
+ // If we haven't received any auth state from the client, just use what the server has so we have
841
+ // something to send to observers.
842
+ var currentState = this.stateSystem.GetCurrentState(this.serverLastProcessedCommandNumber, tick, time);
843
+ this.stateHistory.Set(tick, currentState);
844
+ }
827
845
  }
828
846
 
829
847
  public void NonAuthServerSetSnapshot(int tick)
@@ -977,7 +995,7 @@ namespace Code.Network.StateSystem
977
995
  if (!this.observerHistory.GetAround(NetworkTime.time, out State prevState, out State nextState))
978
996
  {
979
997
  // if (clientTime < this.observerHistory.Keys[0]) return; // Our local time hasn't advanced enough to render the positions reported. No need to log debug
980
- // Debug.LogWarning("Frame " + Time.frameCount + " not enough state history for rendering. " + this.observerHistory.Keys.Count +
998
+ // Debug.LogWarning("Frame " + Time.frameCount + " not enough state history for rendering " + this.name + ". " + this.observerHistory.Keys.Count +
981
999
  // " entries. First " + this.observerHistory.Keys[0] + " Last " +
982
1000
  // this.observerHistory.Keys[^1] + " Target " + NetworkTime.time + " Buffer is: " + NetworkClient.bufferTime + " Estimated Latency (1 way): " +
983
1001
  // (NetworkTime.rtt / 2) + " TScale: " + Time.timeScale);
@@ -1177,7 +1195,7 @@ namespace Code.Network.StateSystem
1177
1195
  // Debug.Log("Server received command " + command.commandNumber + " for " + this.gameObject.name);
1178
1196
  // This should only occur if the server is authoritative.
1179
1197
  if (!serverAuth) {
1180
- Debug.LogWarning($"Received input command from {this.name}, but the networking mode is not server authoritative. Command will be ignored.");
1198
+ // Debug.LogWarning($"Received input command from {this.name}, but the networking mode is not server authoritative. Command will be ignored.");
1181
1199
  return;
1182
1200
  }
1183
1201
 
@@ -1198,8 +1216,8 @@ namespace Code.Network.StateSystem
1198
1216
  // Reject commands if our buffer is full.
1199
1217
  if (this.serverCommandBuffer.Count > this.serverCommandBufferMaxSize)
1200
1218
  {
1201
- Debug.LogWarning("Dropping command " + command.commandNumber +
1202
- " for "+ this.name + " due to exceeding command buffer size. First command in buffer is " + this.serverCommandBuffer.Values[0]);
1219
+ // Debug.LogWarning("Dropping command " + command.commandNumber +
1220
+ // " for "+ this.name + " due to exceeding command buffer size. First command in buffer is " + this.serverCommandBuffer.Values[0]);
1203
1221
  return;
1204
1222
  }
1205
1223