gg.easy.airship 0.1.1998 → 0.1.2000

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.
@@ -2,26 +2,32 @@ using System;
2
2
  using System.IO;
3
3
  using System.Threading.Tasks;
4
4
  using Airship.DevConsole;
5
+ using Code.Http.Internal;
6
+ using Code.Platform.Shared;
5
7
  using JetBrains.Annotations;
8
+ using MiniJSON;
6
9
  using Mirror;
10
+ using UnityEditor.PackageManager;
7
11
  using UnityEngine;
8
12
  using UnityEngine.Networking;
9
13
  using UnityEngine.Profiling;
10
14
 
11
- struct FileIOCreateRequest {
12
- public string file;
13
- public int maxDownloads;
14
- public bool autoDelete;
15
+ struct SignedUrlRequest {
16
+ public string type;
17
+ public string name;
18
+ public string contentType;
19
+ public long contentLength;
15
20
  }
16
21
 
17
22
 
18
- struct FileIOCreateResponse {
19
- public bool success;
20
- public int status;
23
+ struct SignedUrlResponse
24
+ {
25
+ public string id;
26
+ public string url;
27
+ }
21
28
 
22
- public string key;
23
- public string name;
24
- public string link;
29
+ struct ArtifactDownloadResponse {
30
+ public string url;
25
31
  }
26
32
 
27
33
  struct ServerProfileRequest {
@@ -30,21 +36,32 @@ struct ServerProfileRequest {
30
36
 
31
37
  namespace Code.Health
32
38
  {
33
- public enum AirshipProfileContext {
34
- Server,
35
- Client,
39
+ public struct ClientProfileUploadRequest : NetworkMessage
40
+ {
41
+ public string logLocation;
42
+ public float duration;
43
+ public long contentSize;
44
+ }
45
+
46
+ public struct ClientProfileUploadResponse : NetworkMessage
47
+ {
48
+ public string logLocation;
49
+ public string id;
50
+ public string url;
51
+ public float duration;
36
52
  }
37
53
 
38
- public struct StartProfilingMessage : NetworkMessage {
54
+ public struct StartServerProfileMessage : NetworkMessage {
39
55
  public int DurationSecs;
40
56
  }
41
57
 
42
- public struct ProfileCompleteMessage : NetworkMessage {
43
- public string link;
58
+ public struct ServerProfileCompleteMessage : NetworkMessage
59
+ {
60
+ public string gameId;
61
+ public string artifactId;
44
62
  }
45
63
 
46
64
  public class AirshipProfileExporter : MonoBehaviour {
47
- public static string fileIOKey = "LGF5JOI.F0YF0ET-N6PMPS6-NWGVZEW-9984TYP"; // TODO throw out this key (it lives in git).
48
65
  private static AirshipProfileExporter _instance;
49
66
  public static AirshipProfileExporter Instance => _instance;
50
67
  private bool lastProfilerEnabled = false;
@@ -60,13 +77,15 @@ namespace Code.Health
60
77
 
61
78
  private void Start() {
62
79
  if (RunCore.IsServer()) {
63
- NetworkServer.RegisterHandler<StartProfilingMessage>(OnStartProfilingMessage, false);
80
+ NetworkServer.RegisterHandler<StartServerProfileMessage>(OnStartProfilingMessage, false);
81
+ NetworkServer.RegisterHandler<ClientProfileUploadRequest>(OnClientUploadRequest, false);
64
82
  }
65
83
  if (RunCore.IsClient()) {
66
- NetworkClient.RegisterHandler<ProfileCompleteMessage>(OnProfileCompleteMessage);
84
+ NetworkClient.RegisterHandler<ServerProfileCompleteMessage>(OnServerProfileCompleteMessage);
85
+ NetworkClient.RegisterHandler<ClientProfileUploadResponse>(OnClientUploadResponse);
67
86
  }
68
87
 
69
- DevConsole.AddCommand(Command.Create<AirshipProfileContext, int>(
88
+ DevConsole.AddCommand(Command.Create<string, int>(
70
89
  "profile",
71
90
  "",
72
91
  "Starts and uploads a profile. Once complete the download link will be printed.",
@@ -78,11 +97,11 @@ namespace Code.Health
78
97
  return;
79
98
  }
80
99
 
81
- if (context == AirshipProfileContext.Client) {
100
+ if (context.ToLower() == "client") {
82
101
  StartProfiling(d, null);
83
- } else {
102
+ } else if (context.ToLower() == "server") {
84
103
  Debug.Log("Starting a server profile, view server console to monitor progress.");
85
- NetworkClient.Send(new StartProfilingMessage { DurationSecs = d });
104
+ NetworkClient.Send(new StartServerProfileMessage { DurationSecs = d });
86
105
  }
87
106
  }));
88
107
  }
@@ -94,14 +113,47 @@ namespace Code.Health
94
113
  }
95
114
  }
96
115
 
97
- public void OnStartProfilingMessage(NetworkConnectionToClient sender, StartProfilingMessage msg) {
116
+ public async void OnClientUploadRequest(NetworkConnectionToClient sender, ClientProfileUploadRequest msg)
117
+ {
118
+ var urlData = await this.GetSignedUrl(msg.duration, msg.contentSize);
119
+ sender.Send(new ClientProfileUploadResponse
120
+ {
121
+ logLocation = msg.logLocation,
122
+ duration = msg.duration,
123
+ url = urlData.url,
124
+ id = urlData.id
125
+ });
126
+ }
127
+
128
+ public async void OnClientUploadResponse(ClientProfileUploadResponse msg)
129
+ {
130
+ this.Upload(new SignedUrlResponse()
131
+ {
132
+ id = msg.id,
133
+ url = msg.url
134
+ }, msg.logLocation, msg.duration, null);
135
+ }
136
+
137
+ public void OnStartProfilingMessage(NetworkConnectionToClient sender, StartServerProfileMessage msg) {
98
138
  // TODO Validate sender is dev
99
139
  StartProfiling(msg.DurationSecs, sender);
100
140
  }
101
141
 
102
- public void OnProfileCompleteMessage(ProfileCompleteMessage msg) {
103
- Debug.Log($"Profile uploaded: <a href=\"{msg.link}\">{msg.link}</a> (copied to your clipboard)");
104
- GUIUtility.systemCopyBuffer = msg.link;
142
+ public async void OnServerProfileCompleteMessage(ServerProfileCompleteMessage msg)
143
+ {
144
+ var downloadUrl =
145
+ await InternalHttpManager.GetAsync(
146
+ $"{AirshipPlatformUrl.contentService}/artifacts/artifact-id/{msg.artifactId}");
147
+ if (!downloadUrl.success)
148
+ {
149
+ Debug.Log($"Profile Uploaded: <a href=\"https://create.airship.gg/dashboard/organization/game/artifacts?activeGame={msg.gameId}\">View it on the Create site.</a> (copied to your clipboard)");
150
+ return;
151
+ }
152
+
153
+ var data = JsonUtility.FromJson<ArtifactDownloadResponse>(downloadUrl.data);
154
+
155
+ Debug.Log($"Profile uploaded: <a href=\"{data.url}\">Download here.</a> (copied to your clipboard)");
156
+ GUIUtility.systemCopyBuffer = data.url;
105
157
  }
106
158
 
107
159
  public void StartProfiling(int durationSecs, [CanBeNull] NetworkConnectionToClient profileInitiator) {
@@ -126,33 +178,59 @@ namespace Code.Health
126
178
  private async void StopProfilingAfterDelay(string logPath, float durationSecs, [CanBeNull] NetworkConnectionToClient profileInitiator) {
127
179
  await Task.Delay((int)(durationSecs * 1000));
128
180
  Profiler.enabled = false;
129
- Debug.Log($"Profiling completed. Uploading file...");
130
- Upload(logPath, durationSecs, profileInitiator);
181
+ var info = new FileInfo(logPath);
182
+
183
+ Debug.Log($"Profiling completed. Retrieving upload URL...");
184
+ if (RunCore.IsClient())
185
+ {
186
+ NetworkClient.Send(new ClientProfileUploadRequest
187
+ {
188
+ contentSize = info.Length,
189
+ logLocation = logPath
190
+ });
191
+ }
192
+ else
193
+ {
194
+ var urlData = await this.GetSignedUrl(durationSecs, info.Length);
195
+ Upload(urlData, logPath, durationSecs, profileInitiator);
196
+ }
131
197
  }
132
198
 
133
- private async void Upload(string logPath, float durationSecs, [CanBeNull] NetworkConnectionToClient profileInitiator) {
134
- var uploadFilePath = logPath;
199
+ private async Task<SignedUrlResponse> GetSignedUrl(float duration, long length)
200
+ {
201
+ var body = new SignedUrlRequest()
202
+ {
203
+ type = "MICRO_PROFILE",
204
+ name = RunCore.IsClient() ? $"Client Profile ({duration}s)" : $"Server Profile ({duration}s)",
205
+ contentType = "application/octet-stream",
206
+ contentLength = length
207
+ };
208
+ var response = await InternalHttpManager.PostAsync($"{AirshipPlatformUrl.contentService}/artifacts/signed-url", JsonUtility.ToJson(body));
209
+ if (!response.success)
210
+ {
211
+ throw new Exception("Unable to get upload URL for profile.");
212
+ }
135
213
 
136
- var form = new WWWForm();
137
- form.AddField("title", $"Server Profile ({durationSecs}s)");
138
- form.AddField("description", "Learn more: https://docs.airship.gg/optimization/server-profiler");
139
- form.AddField("autoDelete", "false");
140
- form.AddField("maxDownloads", "100");
141
- form.AddField("expires", "1w");
214
+ return JsonUtility.FromJson<SignedUrlResponse>(response.data);
215
+ }
216
+
217
+ private async void Upload(SignedUrlResponse urlData, string logPath, float durationSecs, [CanBeNull] NetworkConnectionToClient profileInitiator)
218
+ {
219
+ Debug.Log("Uploading profile to backend...");
220
+ var uploadFilePath = logPath;
142
221
  var fileData = await File.ReadAllBytesAsync(uploadFilePath);
143
222
  File.Delete(uploadFilePath);
144
223
 
224
+ var form = new WWWForm();
145
225
  form.AddBinaryData("file", fileData, Path.GetFileName(uploadFilePath));
146
- using var www = UnityWebRequest.Post("https://file.io/?expires=1w", form);
147
- www.SetRequestHeader("Authorization", "Bearer " + fileIOKey);
226
+ using var www = UnityWebRequest.Post(urlData.url, form);
148
227
  MonitorUploadProgress(www);
149
228
  await UnityWebRequestProxyHelper.ApplyProxySettings(www).SendWebRequest();
150
229
 
151
- var resp = JsonUtility.FromJson<FileIOCreateResponse>(www.downloadHandler.text);
152
230
  if (profileInitiator != null && profileInitiator.isReady) {
153
- profileInitiator.Send(new ProfileCompleteMessage { link = resp.link });
231
+ profileInitiator.Send(new ServerProfileCompleteMessage { artifactId = urlData.id });
154
232
  }
155
- Debug.Log($"Profile uploaded: <a href=\"{resp.link}\">{resp.link}</a> (copied to your clipboard)");
233
+ Debug.Log($"Profile uploaded.");
156
234
  }
157
235
 
158
236
  private async void MonitorUploadProgress(UnityWebRequest req) {
@@ -12,15 +12,24 @@ public static class ChunkSerializer {
12
12
 
13
13
  writer.WriteVector3Int(key);
14
14
 
15
+ var voxelDataLengthBytes = value.readWriteVoxel.Length * sizeof(short);
16
+ var colDataLengthBytes = value.color.Length * sizeof(uint);
17
+
18
+ writer.WriteInt(voxelDataLengthBytes);
19
+ writer.WriteInt(colDataLengthBytes);
20
+
15
21
  // Input byte array
16
- byte[] byteArray = new byte[value.readWriteVoxel.Length * sizeof(short)];
22
+ byte[] byteArray = new byte[voxelDataLengthBytes];
17
23
  Buffer.BlockCopy(value.readWriteVoxel, 0, byteArray, 0, byteArray.Length);
24
+ byte[] colArray = new byte[colDataLengthBytes];
25
+ Buffer.BlockCopy(value.color, 0, colArray, 0, colArray.Length);
18
26
 
19
27
  // Compress the byte array
20
28
  byte[] compressedBytes;
21
29
  using (MemoryStream ms = new MemoryStream()) {
22
30
  using (DeflateStream deflateStream = new DeflateStream(ms, CompressionMode.Compress)) {
23
31
  deflateStream.Write(byteArray, 0, byteArray.Length);
32
+ deflateStream.Write(colArray, 0, colArray.Length);
24
33
  }
25
34
  compressedBytes = ms.ToArray();
26
35
  }
@@ -31,6 +40,9 @@ public static class ChunkSerializer {
31
40
  //create it from the reader
32
41
  Vector3Int key = reader.ReadVector3Int();
33
42
 
43
+ var voxelDataLength = reader.ReadInt();
44
+ var colorDataLength = reader.ReadInt();
45
+
34
46
  Chunk chunk = VoxelWorld.CreateChunk(key);
35
47
 
36
48
  // byte[] byteArray = new byte[16 * 16 * 16 * 2]; // 2 because they are shorts
@@ -41,7 +53,8 @@ public static class ChunkSerializer {
41
53
  deflateStream.CopyTo(outputStream);
42
54
  // chunk.readWriteVoxel = outputStream.ToArray();
43
55
  var output = outputStream.ToArray();
44
- Buffer.BlockCopy(output, 0, chunk.readWriteVoxel, 0, output.Length);
56
+ Buffer.BlockCopy(output, 0, chunk.readWriteVoxel, 0, voxelDataLength);
57
+ Buffer.BlockCopy(output, voxelDataLength, chunk.color, 0, colorDataLength);
45
58
  }
46
59
  }
47
60
  }
@@ -744,9 +744,11 @@ public class VoxelWorldEditor : UnityEditor.Editor {
744
744
  var oldColor = world.GetVoxelColorAt(voxelPos);
745
745
  Color newCol;
746
746
  if (e.shift) {
747
- newCol = new Color32((byte) (Math.Max(oldColor.r + -10, 0)), oldColor.g, oldColor.b, oldColor.a);
747
+ newCol = new Color32((byte) (Math.Max(oldColor.r + -5, 0)), oldColor.g, oldColor.b, oldColor.a);
748
748
  } else {
749
- newCol = new Color32((byte) (Math.Min(oldColor.r + 10, 255)), oldColor.g, oldColor.b, oldColor.a);
749
+ var colIncr = 5;
750
+ if (oldColor.r == 0) colIncr = 1; // If just being lightly painted to mark as receiving color
751
+ newCol = new Color32((byte) (Math.Min(oldColor.r + colIncr, 255)), oldColor.g, oldColor.b, oldColor.a);
750
752
  }
751
753
  VoxelEditManager.Instance.ColorVoxel(world, voxelPos, newCol);
752
754
  }