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.
- package/Runtime/Code/Health/AirshipProfileExporter.cs +120 -42
- package/Runtime/Code/VoxelWorld/ChunkSerializer.cs +15 -2
- package/Runtime/Code/VoxelWorld/Editor/VoxelWorldEditor.cs +4 -2
- package/Runtime/Code/VoxelWorld/VoxelMeshProcessor.cs +131 -75
- package/Runtime/Code/VoxelWorld/VoxelQuarterBlock.cs +122 -122
- package/Runtime/Code/VoxelWorld/VoxelWorld.cs +1 -1
- package/package.json +1 -1
|
@@ -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
|
|
12
|
-
public string
|
|
13
|
-
public
|
|
14
|
-
public
|
|
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
|
|
19
|
-
|
|
20
|
-
public
|
|
23
|
+
struct SignedUrlResponse
|
|
24
|
+
{
|
|
25
|
+
public string id;
|
|
26
|
+
public string url;
|
|
27
|
+
}
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
public string
|
|
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
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
54
|
+
public struct StartServerProfileMessage : NetworkMessage {
|
|
39
55
|
public int DurationSecs;
|
|
40
56
|
}
|
|
41
57
|
|
|
42
|
-
public struct
|
|
43
|
-
|
|
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<
|
|
80
|
+
NetworkServer.RegisterHandler<StartServerProfileMessage>(OnStartProfilingMessage, false);
|
|
81
|
+
NetworkServer.RegisterHandler<ClientProfileUploadRequest>(OnClientUploadRequest, false);
|
|
64
82
|
}
|
|
65
83
|
if (RunCore.IsClient()) {
|
|
66
|
-
NetworkClient.RegisterHandler<
|
|
84
|
+
NetworkClient.RegisterHandler<ServerProfileCompleteMessage>(OnServerProfileCompleteMessage);
|
|
85
|
+
NetworkClient.RegisterHandler<ClientProfileUploadResponse>(OnClientUploadResponse);
|
|
67
86
|
}
|
|
68
87
|
|
|
69
|
-
DevConsole.AddCommand(Command.Create<
|
|
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 ==
|
|
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
|
|
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
|
|
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
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
130
|
-
|
|
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
|
|
134
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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(
|
|
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
|
|
231
|
+
profileInitiator.Send(new ServerProfileCompleteMessage { artifactId = urlData.id });
|
|
154
232
|
}
|
|
155
|
-
Debug.Log($"Profile uploaded
|
|
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[
|
|
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,
|
|
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 + -
|
|
747
|
+
newCol = new Color32((byte) (Math.Max(oldColor.r + -5, 0)), oldColor.g, oldColor.b, oldColor.a);
|
|
748
748
|
} else {
|
|
749
|
-
|
|
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
|
}
|