gg.easy.airship 0.1.2162 → 0.1.2164

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 (35) hide show
  1. package/.editorconfig +9 -0
  2. package/Editor/BuildMenu.cs +25 -25
  3. package/Runtime/Code/AirshipConst.cs +2 -2
  4. package/Runtime/Code/Analytics/ClientFolderUploader.cs +145 -0
  5. package/Runtime/Code/Analytics/ClientFolderUploader.cs.meta +2 -0
  6. package/Runtime/Code/Auth/Socket/SocketManager.cs +8 -0
  7. package/Runtime/Code/Bootstrap/AirshipEntryPoint.cs +13 -0
  8. package/Runtime/Code/Bootstrap/AirshipEntryPoint.cs.meta +3 -0
  9. package/Runtime/Code/Bootstrap/AirshipLogHandler.cs +22 -0
  10. package/Runtime/Code/Bootstrap/AirshipLogHandler.cs.meta +3 -0
  11. package/Runtime/Code/Bootstrap/ClientBootstrap.cs +4 -0
  12. package/Runtime/Code/Bootstrap/SignalHandler.cs +37 -24
  13. package/Runtime/Code/CoreUI/Login/LoginApp.cs +1 -1
  14. package/Runtime/Code/Luau/LuauCoreCallbacks.cs +0 -5
  15. package/Runtime/Code/LuauAPI/FrameTimingManagerAPI.cs +10 -0
  16. package/Runtime/Code/LuauAPI/FrameTimingManagerAPI.cs.meta +3 -0
  17. package/Runtime/Code/Network/AirshipNetworkManager.cs +3 -1
  18. package/Runtime/Code/Network/StateSystem/AirshipNetworkedStateManager.cs +55 -49
  19. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterMovement.cs +127 -31
  20. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterSnapshotData.cs +33 -33
  21. package/Runtime/Code/TSCodeGen/TypeGenerator.cs +1 -0
  22. package/Runtime/Code/VoxelWorld/Resources/VoxelWorldDefaultBlocks/DefaultDirt/DefaultDirt.asset +26 -6
  23. package/Runtime/Code/VoxelWorld/Resources/VoxelWorldDefaultBlocks/DefaultGrass/DefaultGrass.asset +30 -10
  24. package/Runtime/Code/VoxelWorld/VoxelMeshCopy.cs +155 -138
  25. package/Runtime/DevConsole/Resources/Prefabs/FAB_DevConsole.Instance.prefab +305 -1
  26. package/Runtime/Plugins/Android/libLuauPlugin.so +0 -0
  27. package/Runtime/Plugins/Linux/libLuauPlugin.so +0 -0
  28. package/Runtime/Plugins/Mac/LuauPlugin.bundle/Contents/MacOS/LuauPlugin +0 -0
  29. package/Runtime/Plugins/Windows/x64/LuauPlugin.dll +0 -0
  30. package/Runtime/Plugins/Windows/x64/LuauPlugin.pdb +0 -0
  31. package/Runtime/Plugins/iOS/LuauPluginIos.a +0 -0
  32. package/Runtime/Scenes/CoreScene.unity +526 -370
  33. package/Runtime/Scenes/Login.unity +414 -369
  34. package/Runtime/Scenes/MainMenu.unity +87 -42
  35. package/package.json +1 -1
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
@@ -49,38 +49,38 @@ namespace Editor {
49
49
  }
50
50
 
51
51
  public static void BuildLinuxServerStaging() {
52
- PlayerSettings.SetScriptingDefineSymbols(NamedBuildTarget.Server, new string[] {"AIRSHIP_STAGING", "AIRSHIP_PLAYER", "AIRSHIP_INTERNAL"});
53
- BuildLinuxServer();
52
+ BuildLinuxServer(new []{"AIRSHIP_STAGING"});
54
53
  }
55
-
54
+
56
55
  #if AIRSHIP_PLAYER
57
56
  [MenuItem("Airship/Create Binary/Server/Linux", priority = 80)]
58
57
  #endif
59
- public static void BuildLinuxServer() {
60
- OnBuild();
61
- EditorBuildSettingsScene[] scenes = {
62
- new("Packages/gg.easy.airship/Runtime/Scenes/MainMenu.unity", true),
63
- new("Packages/gg.easy.airship/Runtime/Scenes/CoreScene.unity", true),
64
- new("Packages/gg.easy.airship/Runtime/Scenes/Login.unity", true)
65
- };
66
- EditorBuildSettings.scenes = scenes;
58
+ public static void BuildLinuxServerProduction() {
59
+ BuildLinuxServer(new string[]{});
60
+ }
61
+
67
62
 
63
+ public static void BuildLinuxServer(string[] extraDefines) {
64
+ OnBuild();
68
65
  FileUtil.DeleteFileOrDirectory("build/StandaloneLinux64");
69
66
 
70
- // This should probably be NamedBuildTarget.Server (rather than Standalone), but that does cause some issues.
71
- // We will want to review this again in the future as a possible optimization.
72
- PlayerSettings.SetScriptingBackend(NamedBuildTarget.Standalone, ScriptingImplementation.IL2CPP);
73
- PlayerSettings.dedicatedServerOptimizations = true;
74
- PlayerSettings.insecureHttpOption = InsecureHttpOption.AlwaysAllowed;
67
+ BuildProfile buildProfile =
68
+ AssetDatabase.LoadAssetAtPath<BuildProfile>("Assets/Settings/Build Profiles/Dedicated Server (Linux).asset");
69
+ buildProfile.overrideGlobalScenes = true;
70
+ buildProfile.scenes = new[] {
71
+ new EditorBuildSettingsScene("Packages/gg.easy.airship/Runtime/Scenes/CoreScene.unity", true)
72
+ };
73
+ buildProfile.scriptingDefines = new[] { "UNITY_SERVER", "AIRSHIP_PLAYER", "AIRSHIP_INTERAL" }.Concat(extraDefines).ToArray();
74
+ BuildProfile.SetActiveBuildProfile(buildProfile);
75
+
76
+ Debug.Log("Building with " + buildProfile.scenes.Length + " scenes");
75
77
 
76
- EditorUserBuildSettings.managedDebuggerFixedPort = 55000;
77
- var options = new BuildPlayerOptions();
78
- options.scenes = new[] { "Packages/gg.easy.airship/Runtime/Scenes/CoreScene.unity" };
79
- options.locationPathName = $"build/StandaloneLinux64/{ServerExecutableName}";
80
- options.target = BuildTarget.StandaloneLinux64;
81
- options.extraScriptingDefines = new[] { "UNITY_SERVER", "AIRSHIP_PLAYER", "AIRSHIP_INTERAL" };
82
- options.subtarget = (int)StandaloneBuildSubtarget.Server;
83
- options.options |= BuildOptions.Development; //Enable the profiler
78
+ var options = new BuildPlayerWithProfileOptions() {
79
+ buildProfile = buildProfile,
80
+ locationPathName = $"build/StandaloneLinux64/{ServerExecutableName}",
81
+ options = BuildOptions.Development,
82
+ };
83
+
84
84
  var report = BuildPipeline.BuildPlayer(options);
85
85
  var summary = report.summary;
86
86
  switch (summary.result) {
@@ -94,7 +94,7 @@ namespace Editor {
94
94
  Debug.Log("Build Linux unexpected result:" + summary.result);
95
95
  break;
96
96
  }
97
-
97
+
98
98
  CreateAssetBundles.AddAllGameBundleScenes();
99
99
  }
100
100
 
@@ -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,145 @@
1
+ using System;
2
+ using System.IO;
3
+ using System.IO.Compression;
4
+ using System.Threading.Tasks;
5
+ using Code.Http.Internal;
6
+ using Code.Http.Public;
7
+ using Code.Platform.Shared;
8
+ using Proyecto26;
9
+ using UnityEngine;
10
+
11
+ namespace Code.Analytics {
12
+ [Serializable]
13
+ public class PostArtifactResponse {
14
+ public string id;
15
+ public string url;
16
+ }
17
+
18
+ [Serializable]
19
+ public class RequestBody {
20
+ public string type;
21
+ public string name;
22
+ public string contentType;
23
+ public long contentLength;
24
+ }
25
+
26
+ public class ClientFolderUploader : MonoBehaviour {
27
+
28
+ // Start in the past otherwise they can't do this for the first 10 seconds since time starts at 0.
29
+ private float timeOfLastUpload = -10;
30
+
31
+ public void ButtonClick() {
32
+ if (Time.unscaledTime - timeOfLastUpload < 10) {
33
+ Debug.LogWarning("[ClientFolderUploader] Upload already in progress or too soon after last upload");
34
+ return;
35
+ }
36
+ timeOfLastUpload = Time.unscaledTime;
37
+
38
+ _ = UploadAsync();
39
+ }
40
+
41
+ private async Task UploadAsync() {
42
+ try {
43
+ await Upload();
44
+ Debug.Log("[ClientFolderUploader] Upload completed successfully");
45
+ } catch (Exception ex) {
46
+ Debug.LogError($"[ClientFolderUploader] Upload failed: {ex.Message}");
47
+ }
48
+ }
49
+
50
+ public async Task Upload() {
51
+ try {
52
+ var path = Path.GetDirectoryName(Application.consoleLogPath);
53
+
54
+ var zipPath = Path.Combine(Application.temporaryCachePath, "logs.zip");
55
+ if (File.Exists(zipPath)) {
56
+ File.Delete(zipPath);
57
+ }
58
+
59
+ var playerLogFile = Path.Combine(path, "Player.log");
60
+ var playerPrevLogFile = Path.Combine(path, "Player-prev.log");
61
+ var editorLogFile = Path.Combine(path, "Editor.log");
62
+ var editorPrevLogFile = Path.Combine(path, "Editor-prev.log");
63
+
64
+ Debug.Log("[ClientFolderUploader] Creating zip archive");
65
+ try {
66
+ using (var archive = ZipFile.Open(zipPath, ZipArchiveMode.Create)) {
67
+ var fileExists = false;
68
+ if (File.Exists(playerLogFile)) {
69
+ fileExists = true;
70
+ Debug.Log("[ClientFolderUploader] Adding Player.log");
71
+ archive.CreateEntryFromFile(playerLogFile, "Player.log");
72
+ }
73
+
74
+ if (File.Exists(playerPrevLogFile)) {
75
+ fileExists = true;
76
+ Debug.Log("[ClientFolderUploader] Adding Player-prev.log");
77
+ archive.CreateEntryFromFile(playerPrevLogFile, "Player-prev.log");
78
+ }
79
+
80
+ if (File.Exists(editorLogFile)) {
81
+ fileExists = true;
82
+ Debug.Log("[ClientFolderUploader] Adding Editor.log");
83
+ archive.CreateEntryFromFile(editorLogFile, "Editor.log");
84
+ }
85
+
86
+ if (File.Exists(editorPrevLogFile)) {
87
+ fileExists = true;
88
+ Debug.Log("[ClientFolderUploader] Adding Editor-prev.log");
89
+ archive.CreateEntryFromFile(editorPrevLogFile, "Editor-prev.log");
90
+ }
91
+
92
+ if (!fileExists) {
93
+ return;
94
+ }
95
+ }
96
+ } catch (Exception ex) {
97
+ Debug.LogError($"[ClientFolderUploader] Zip creation failed: {ex.Message}");
98
+ throw;
99
+ }
100
+
101
+ var contentType = "application/zip";
102
+ var contentLength = new FileInfo(zipPath).Length;
103
+
104
+ var body = new RequestBody {
105
+ type = "CLIENT_DEBUG_ARCHIVE",
106
+ name = "PlayerLogs.zip",
107
+ contentType = contentType,
108
+ contentLength = contentLength,
109
+ };
110
+
111
+ Debug.Log("[ClientFolderUploader] Creating artifact");
112
+ var url = $"{AirshipPlatformUrl.contentService}/artifacts/platform/signed-url";
113
+
114
+ Http.HttpResponse res;
115
+ if (String.IsNullOrEmpty(InternalHttpManager.authToken)) {
116
+ res = await HttpManager.PostAsync(url, JsonUtility.ToJson(body));
117
+ } else {
118
+ res = await InternalHttpManager.PostAsync(url, JsonUtility.ToJson(body));
119
+ }
120
+
121
+ if (res.statusCode < 200 || res.statusCode >= 300) {
122
+ Debug.LogError($"[ClientFolderUploader] Error response from server: {res.statusCode} - {res.error}");
123
+ throw new Exception($"Failed to get signed URL: {res.error}");
124
+ }
125
+
126
+ var response = JsonUtility.FromJson<PostArtifactResponse>(res.data);
127
+
128
+ Debug.Log("[ClientFolderUploader] Uploading file");
129
+ await HttpManager.PutAsync(new RequestHelper() {
130
+ Uri = response.url,
131
+ BodyRaw = File.ReadAllBytes(zipPath),
132
+ Headers = new System.Collections.Generic.Dictionary<string, string>
133
+ {
134
+ { "Content-Type", contentType },
135
+ },
136
+ }, "");
137
+
138
+ File.Delete(zipPath);
139
+ } catch (Exception ex) {
140
+ Debug.LogError($"[ClientFolderUploader] Error during upload process: {ex.Message}");
141
+ throw;
142
+ }
143
+ }
144
+ }
145
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 474c8118d514c47d2b470bdd6dd04d84
@@ -5,6 +5,7 @@ using System.Threading.Tasks;
5
5
  using Airship.DevConsole;
6
6
  using Code.Auth;
7
7
  using Code.Http.Internal;
8
+ using Code.Network;
8
9
  using Code.Platform.Shared;
9
10
  using Code.Util;
10
11
  using Luau;
@@ -62,6 +63,13 @@ public class SocketManager : Singleton<SocketManager> {
62
63
  Debug.LogError("Failed to join game: " + res.error);
63
64
  }
64
65
  }));
66
+
67
+ DevConsole.AddCommand(Command.Create<string>("ping", "", "Measure ping to an airship server cluster",
68
+ Parameter.Create("Ping Server IP", "IP of the Airship cluster ping server."), (serverIp) => {
69
+ UdpPingTool.GetPing(serverIp, 1000).ContinueWith((result) => {
70
+ Debug.Log($"Latency to {serverIp.Trim()} is {result.Result}ms");
71
+ });
72
+ }));
65
73
  }
66
74
 
67
75
  public static async Task<bool> ConnectAsyncInternal() {
@@ -0,0 +1,13 @@
1
+ using System;
2
+ using Code.Bootstrap;
3
+ using UnityEngine;
4
+
5
+
6
+ /// <summary>
7
+ /// This singleton is exists in the CoreScene, MainMenu, and Login scene.
8
+ /// </summary>
9
+ public class AirshipEntryPoint : Singleton<AirshipEntryPoint> {
10
+ private void Start() {
11
+ Debug.unityLogger.logHandler = new AirshipLogHandler();
12
+ }
13
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 1441bc18c60b412884336c9740a95575
3
+ timeCreated: 1753828357
@@ -0,0 +1,22 @@
1
+ using System;
2
+ using UnityEngine;
3
+ using Object = UnityEngine.Object;
4
+
5
+ namespace Code.Bootstrap {
6
+ public class AirshipLogHandler : ILogHandler {
7
+ private readonly ILogHandler defaultLogHandler = Debug.unityLogger.logHandler;
8
+
9
+ public void LogFormat(LogType logType, Object context, string format, params object[] args) {
10
+ string message = string.Format(format, args);
11
+
12
+ // TextMeshPro warning about unsupported character.
13
+ if (message.Contains("Unicode value \\u0007")) return;
14
+
15
+ defaultLogHandler.LogFormat(logType, context, format, args);
16
+ }
17
+
18
+ public void LogException(Exception exception, Object context) {
19
+ defaultLogHandler.LogException(exception, context);
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: ff48f1daed464a5aa73f34da054f6e7f
3
+ timeCreated: 1753828486
@@ -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
  }
@@ -1,10 +1,6 @@
1
1
  using System.Collections;
2
- using System.Threading;
2
+ using System.Runtime.InteropServices;
3
3
  using Code.Util;
4
- #if UNITY_STANDALONE_LINUX || UNITY_EDITOR_LINUX
5
- using Mono.Unix;
6
- using Mono.Unix.Native;
7
- #endif
8
4
  using UnityEngine;
9
5
 
10
6
  namespace Code.Bootstrap {
@@ -12,34 +8,51 @@ namespace Code.Bootstrap {
12
8
  public ServerBootstrap serverBootstrap;
13
9
  public UnityMainThreadDispatcher unityMainThread;
14
10
 
15
-
16
11
  #if UNITY_STANDALONE_LINUX || UNITY_EDITOR_LINUX
17
- void Start() {
18
- var thread = new Thread(CheckForSignals);
19
- thread.Start();
12
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
13
+ private delegate void SignalDelegate();
14
+
15
+ [DllImport("signalhandler", CallingConvention = CallingConvention.Cdecl)]
16
+ private static extern void RegisterSigTermHandler(SignalDelegate callback);
17
+
18
+ private static SignalDelegate cachedDelegate;
19
+
20
+ [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
21
+ private static void Init()
22
+ {
23
+ cachedDelegate = OnSigTerm;
24
+ RegisterSigTermHandler(cachedDelegate);
25
+ Debug.Log("Unix SIGTERM handler registered");
20
26
  }
21
27
 
22
- private void CheckForSignals() {
23
- while (true) {
24
- var signals = new UnixSignal[] {
25
- new UnixSignal(Signum.SIGTERM)
26
- };
27
- int index = UnixSignal.WaitAny(signals, -1);
28
-
29
- if (index >= 0 && signals[index].IsSet) {
30
- Debug.Log("Sigterm.1");
31
- this.unityMainThread.Enqueue(HandleSigterm());
32
- signals[index].Reset();
33
- }
28
+ // This is called from a POSIX signal context
29
+ [AOT.MonoPInvokeCallback(typeof(SignalDelegate))]
30
+ private static void OnSigTerm()
31
+ {
32
+ Debug.Log("SIGTERM signal received from native");
33
+
34
+ // We can't call Unity APIs directly from signal thread,
35
+ // So we need to dispatch back to main thread
36
+ _hasSigterm = true;
37
+ }
38
+
39
+ private static bool _hasSigterm;
40
+
41
+ private void Update()
42
+ {
43
+ if (_hasSigterm)
44
+ {
45
+ _hasSigterm = false;
46
+ unityMainThread.Enqueue(HandleSigterm());
34
47
  }
35
48
  }
36
49
 
37
- private IEnumerator HandleSigterm() {
50
+ private IEnumerator HandleSigterm()
51
+ {
38
52
  Debug.Log("SIGTERM received. Performing cleanup.");
39
- // Perform your cleanup here
40
53
  serverBootstrap.InvokeOnProcessExit();
41
54
  yield return null;
42
- // Application.Quit();
55
+ Application.Quit();
43
56
  }
44
57
  #endif
45
58
  }
@@ -283,7 +283,7 @@ public class LoginApp : MonoBehaviour {
283
283
  RestClient.Get(new RequestHelper() {
284
284
  Uri = AirshipPlatformUrl.gameCoordinator + (prodApp ? "/auth/steam/in-game" : "/auth/steam/in-game-playtest"),
285
285
  Headers = new Dictionary<string, string>() {
286
- { "Authorization", steamToken }
286
+ { "steam-token", steamToken }
287
287
  },
288
288
  }).Then((gcRes) => {
289
289
  print("gc response: " + gcRes.Text);
@@ -1157,10 +1157,8 @@ public partial class LuauCore : MonoBehaviour {
1157
1157
  static unsafe int CallMethodCallback(LuauContext context, IntPtr thread, int instanceId, IntPtr classNamePtr, int classNameSize, IntPtr methodNamePtr, int methodNameLength, int numParameters, IntPtr firstParameterType, IntPtr firstParameterData, IntPtr firstParameterSize, IntPtr firstParameterIsTable, IntPtr shouldYield) {
1158
1158
  CurrentContext = context;
1159
1159
 
1160
- // if (s_shutdown) return 0;
1161
1160
  Marshal.WriteInt32(shouldYield, 0);
1162
1161
  if (!IsReady) {
1163
- Profiler.EndSample();
1164
1162
  return 0;
1165
1163
  }
1166
1164
 
@@ -1428,7 +1426,6 @@ public partial class LuauCore : MonoBehaviour {
1428
1426
  return returnCount;
1429
1427
  }
1430
1428
 
1431
- Profiler.BeginSample("LuauCore.InvokeMethod");
1432
1429
  try {
1433
1430
  returnValue = finalMethod.Invoke(invokeObj, parsedData.Array);
1434
1431
  }
@@ -1439,8 +1436,6 @@ public partial class LuauCore : MonoBehaviour {
1439
1436
  catch (Exception e) {
1440
1437
  return LuauError(thread,
1441
1438
  "Error: Exception thrown in method " + type.Name + "." + finalMethod.Name + ": " + e);
1442
- } finally {
1443
- Profiler.EndSample();
1444
1439
  }
1445
1440
 
1446
1441
  WriteMethodReturnValuesToThread(thread, type, finalMethod.ReturnType, finalParameters, returnValue, parsedData.Array);
@@ -0,0 +1,10 @@
1
+ using System;
2
+ using UnityEngine;
3
+
4
+ [LuauAPI]
5
+ public class FrameTimingManagerAPI : BaseLuaAPIClass {
6
+ public override Type GetAPIType()
7
+ {
8
+ return typeof(UnityEngine.FrameTimingManager);
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 35174f37579d4286a02956701ad67c2b
3
+ timeCreated: 1753723051
@@ -58,7 +58,9 @@ public class AirshipNetworkManager : NetworkManager {
58
58
  }
59
59
 
60
60
  public override void ConfigureHeadlessFrameRate() {
61
- // Override default behavior of setting target frame rate equal to send rate.
61
+ if (RunCore.IsClient()) return;
62
+
63
+ // Override default behavior of setting target frame rate equal to send rate.
62
64
  // Since we aren't rendering anything, doing tons of Update calls isn't really very important, so we definitely should
63
65
  // lower the target frame rate, we just don't want to use the mirror default of using send rate because we may
64
66
  // set send rate lower than tick rate in the future and we want framerate to always match tick rate for dedicated servers.