gg.easy.airship 0.1.2126 → 0.1.2127
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/Editor/Artifacts/AirshipLocalArtifactDatabase.cs +5 -0
- package/Editor/Artifacts/AirshipReconciliationService.cs +10 -2
- package/Runtime/Code/AirshipConst.cs +2 -2
- package/Runtime/Code/Auth/Socket/SocketManager.cs +10 -0
- package/Runtime/Code/Bundles/CrossSceneState.cs +1 -0
- package/Runtime/Code/Http/HttpResponse.cs +1 -1
- package/Runtime/Code/Luau/ReflectionList.cs +1 -0
- package/Runtime/Code/MainMenu/DisconnectedScreen.cs +22 -0
- package/Runtime/Code/Misc/InternalCameraScreenshotRecorder.cs +130 -128
- package/Runtime/Code/Platform/Shared/AirshipPlatformUrl.cs +4 -0
- package/Runtime/Code/TSCodeGen/Editor/CsToTs/TypeScript/Helper.cs +1 -0
- package/Runtime/Code/TSCodeGen/TypeGenerator.cs +2 -1
- package/Runtime/Code/VoiceChat/AirshipUniVoiceNetwork.cs +51 -10
- package/Runtime/Scenes/Disconnected.unity +810 -98
- package/ThirdParty/UniVoice/Runtime/ChatroomAgent.cs +3 -2
- package/ThirdParty/UniVoice/Runtime/Interfaces/IChatroomNetwork.cs +2 -2
- package/package.json +1 -1
|
@@ -112,6 +112,11 @@ namespace Airship.Editor {
|
|
|
112
112
|
[SerializeField] internal List<ComponentScriptAssetData> scripts = new();
|
|
113
113
|
[SerializeField] internal List<ComponentData> components = new();
|
|
114
114
|
|
|
115
|
+
/// <summary>
|
|
116
|
+
/// Returns if the Database is empty - if it is, it's likely the project is new or freshly pulled
|
|
117
|
+
/// </summary>
|
|
118
|
+
internal static bool isEmpty => instance.scripts.Count == 0 && instance.components.Count == 0;
|
|
119
|
+
|
|
115
120
|
/// <summary>
|
|
116
121
|
/// Gets or creates the script asset data in the artifact database for the given script
|
|
117
122
|
/// </summary>
|
|
@@ -322,11 +322,19 @@ namespace Airship.Editor {
|
|
|
322
322
|
private static void OnComponentReconcile(AirshipReconcileEventData eventData) {
|
|
323
323
|
// Components must have guids
|
|
324
324
|
if (string.IsNullOrEmpty(eventData.Component.guid)) eventData.Component.guid = Guid.NewGuid().ToString();
|
|
325
|
+
|
|
326
|
+
// If an initial setup (e.g. first pull, or new template project)
|
|
327
|
+
if (AirshipLocalArtifactDatabase.isEmpty) {
|
|
328
|
+
// We can run a default reconcile, it wont matter tbh.
|
|
329
|
+
var component = eventData.Component;
|
|
330
|
+
ReconcileComponent(component);
|
|
331
|
+
component.componentHash = component.scriptHash;
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
325
334
|
|
|
326
335
|
if (ReconcilerVersion == ReconcilerVersion.Version2) {
|
|
327
336
|
var component = eventData.Component;
|
|
328
|
-
|
|
329
|
-
|
|
337
|
+
|
|
330
338
|
var isPrefab = PrefabUtility.IsPartOfAnyPrefab(component);
|
|
331
339
|
var prefabOriginalComponent = PrefabUtility.GetCorrespondingObjectFromOriginalSource(component);
|
|
332
340
|
if (isPrefab && prefabOriginalComponent.script != null) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// ReSharper disable InconsistentNaming
|
|
2
2
|
namespace Code {
|
|
3
3
|
public static class AirshipConst {
|
|
4
|
-
public const int playerVersion =
|
|
4
|
+
public const int playerVersion = 4;
|
|
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 =
|
|
9
|
+
public const int minAcceptedPlayerVersionOnServer = 4;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -106,6 +106,16 @@ public class SocketManager : Singleton<SocketManager> {
|
|
|
106
106
|
await Awaitable.MainThreadAsync();
|
|
107
107
|
Instance.OnDisconnected?.Invoke(s);
|
|
108
108
|
};
|
|
109
|
+
|
|
110
|
+
Instance.socket.OnError += async (sender, s) => {
|
|
111
|
+
if (s.StartsWith("User does not have \"GC Edge\" access")) {
|
|
112
|
+
Debug.Log("User does not have \"GC Edge\" access");
|
|
113
|
+
await Awaitable.MainThreadAsync();
|
|
114
|
+
CrossSceneState.kickForceLogout = true;
|
|
115
|
+
TransferManager.Instance.Disconnect(true, "User does not have permission to access Airship");
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
109
119
|
}
|
|
110
120
|
|
|
111
121
|
if (!Instance.socket.Connected) {
|
|
@@ -19,6 +19,7 @@ public static class CrossSceneState
|
|
|
19
19
|
public static ServerTransferData ServerTransferData;
|
|
20
20
|
public static bool UseLocalBundles = false;
|
|
21
21
|
public static string kickMessage = "";
|
|
22
|
+
public static bool kickForceLogout = false;
|
|
22
23
|
public static bool disconnectKicked = false;
|
|
23
24
|
|
|
24
25
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
|
@@ -5,13 +5,35 @@ using UnityEngine.SceneManagement;
|
|
|
5
5
|
|
|
6
6
|
public class DisconnectedScreen : MonoBehaviour {
|
|
7
7
|
public TMP_Text reasonText;
|
|
8
|
+
public GameObject continueButton;
|
|
9
|
+
public GameObject logoutButton;
|
|
10
|
+
public GameObject quitButton;
|
|
8
11
|
|
|
9
12
|
private void Start() {
|
|
10
13
|
this.reasonText.text = CrossSceneState.kickMessage;
|
|
11
14
|
Cursor.lockState = CursorLockMode.None;
|
|
15
|
+
if (CrossSceneState.kickForceLogout) {
|
|
16
|
+
CrossSceneState.kickForceLogout = false;
|
|
17
|
+
this.continueButton.SetActive(false);
|
|
18
|
+
this.logoutButton.SetActive(true);
|
|
19
|
+
this.quitButton.SetActive(true);
|
|
20
|
+
} else {
|
|
21
|
+
this.continueButton.SetActive(true);
|
|
22
|
+
this.logoutButton.SetActive(false);
|
|
23
|
+
this.quitButton.SetActive(false);
|
|
24
|
+
}
|
|
12
25
|
}
|
|
13
26
|
|
|
14
27
|
public void ContinueButton_OnClick() {
|
|
15
28
|
SceneManager.LoadScene("MainMenu");
|
|
16
29
|
}
|
|
30
|
+
|
|
31
|
+
public void QuitButton_OnClick() {
|
|
32
|
+
Application.Quit();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public void LogoutButton_OnClick() {
|
|
36
|
+
AuthManager.ClearSavedAccount();
|
|
37
|
+
SceneManager.LoadScene("Login");
|
|
38
|
+
}
|
|
17
39
|
}
|
|
@@ -11,153 +11,155 @@ public class CameraScreenshotResponse{
|
|
|
11
11
|
public string extension = "";
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
public
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
public SaveFolder saveFolder = SaveFolder.PicturesFolder;
|
|
23
|
-
public bool shouldSaveCaptures = true;
|
|
24
|
-
public int resWidth = 1920;
|
|
25
|
-
public int resHeight = 1080;
|
|
26
|
-
|
|
27
|
-
private const int resDepth = 24;
|
|
28
|
-
private static Texture2D screenShot;
|
|
29
|
-
private static RenderTexture rt;
|
|
30
|
-
|
|
31
|
-
public delegate void OnPictureTaken(Texture2D screenshot);
|
|
32
|
-
public static OnPictureTaken onPictureTaken;
|
|
33
|
-
|
|
34
|
-
public static Texture2D GetScreenshotTexture {
|
|
35
|
-
get {
|
|
36
|
-
return screenShot;
|
|
14
|
+
namespace Assets.Code.Misc {
|
|
15
|
+
[LuauAPI(LuauContext.Protected)]
|
|
16
|
+
public class InternalCameraScreenshotRecorder : Singleton<InternalCameraScreenshotRecorder> {
|
|
17
|
+
public enum SaveFolder {
|
|
18
|
+
ApplicationData,
|
|
19
|
+
PicturesFolder,
|
|
20
|
+
Documents,
|
|
37
21
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return string.Format("{0}/Airship/", folderPath);
|
|
22
|
+
|
|
23
|
+
public SaveFolder saveFolder = SaveFolder.PicturesFolder;
|
|
24
|
+
public bool shouldSaveCaptures = true;
|
|
25
|
+
public int resWidth = 1920;
|
|
26
|
+
public int resHeight = 1080;
|
|
27
|
+
|
|
28
|
+
private const int resDepth = 24;
|
|
29
|
+
private static Texture2D screenShot;
|
|
30
|
+
private static RenderTexture rt;
|
|
31
|
+
|
|
32
|
+
public delegate void OnPictureTaken(Texture2D screenshot);
|
|
33
|
+
public static OnPictureTaken onPictureTaken;
|
|
34
|
+
|
|
35
|
+
public static Texture2D GetScreenshotTexture {
|
|
36
|
+
get {
|
|
37
|
+
return screenShot;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public string ScreenShotName(int width, int height, bool png) {
|
|
42
|
+
return FolderName + string.Format("screen_{0}x{1}_{2}.{3}",
|
|
43
|
+
width, height,
|
|
44
|
+
System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"), png?"png":"jpg");
|
|
62
45
|
}
|
|
63
|
-
}
|
|
64
46
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
47
|
+
public string ScreenShotName(string filename, bool png) {
|
|
48
|
+
return FolderName + filename + (png?".png":".jpg");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public string FolderName{
|
|
52
|
+
get {
|
|
53
|
+
string folderPath = Application.persistentDataPath;
|
|
54
|
+
switch (saveFolder) {
|
|
55
|
+
case SaveFolder.PicturesFolder:
|
|
56
|
+
folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
|
|
57
|
+
break;
|
|
58
|
+
case SaveFolder.Documents:
|
|
59
|
+
folderPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
|
60
|
+
break;
|
|
61
|
+
};
|
|
62
|
+
return string.Format("{0}/Airship/", folderPath);
|
|
63
|
+
}
|
|
68
64
|
}
|
|
69
|
-
}
|
|
70
65
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
private void InitFolder() {
|
|
67
|
+
if (!Directory.Exists (FolderName)) {
|
|
68
|
+
Directory.CreateDirectory(FolderName);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
75
71
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
SaveScreenshot(fileName, superSampleSize, png);
|
|
81
|
-
}
|
|
72
|
+
public static void TakeScreenshot(string fileName = "", int superSampleSize = 1, bool png = true) {
|
|
73
|
+
Instance.InitFolder();
|
|
74
|
+
Instance.StartCoroutine(Instance.TakeScreenshotCo(fileName, superSampleSize, png));
|
|
75
|
+
}
|
|
82
76
|
|
|
77
|
+
private IEnumerator TakeScreenshotCo(string fileName = "", int superSampleSize = 1, bool png = true) {
|
|
78
|
+
//Have to capture at end of frame for ScreenCapture to work
|
|
79
|
+
yield return new WaitForEndOfFrame();
|
|
80
|
+
screenShot = ScreenCapture.CaptureScreenshotAsTexture(superSampleSize);
|
|
81
|
+
SaveScreenshot(fileName, superSampleSize, png);
|
|
82
|
+
}
|
|
83
83
|
|
|
84
|
-
public static void TakeCameraScreenshot(Camera camera, string fileName = "", int superSampleSize = 1) {
|
|
85
|
-
Instance.InitFolder();
|
|
86
|
-
Instance.StartCoroutine(Instance.TakeCameraScreenshotCo(camera, fileName, superSampleSize));
|
|
87
|
-
}
|
|
88
84
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// Have to capture at end of frame for ScreenCapture to work
|
|
93
|
-
yield return new WaitForEndOfFrame();
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
screenShot = new Texture2D(resWidth * superSampleSize, resHeight * superSampleSize, TextureFormat.RGB24, false);
|
|
97
|
-
rt = new RenderTexture(resWidth, resHeight, resDepth);
|
|
98
|
-
camera.enabled = true;
|
|
99
|
-
camera.targetTexture = rt;
|
|
100
|
-
camera.Render();
|
|
101
|
-
RenderTexture.active = rt;
|
|
102
|
-
} catch(Exception e) {
|
|
103
|
-
Debug.LogError("Error saving: " + e.Message);
|
|
85
|
+
public static void TakeCameraScreenshot(Camera camera, string fileName = "", int superSampleSize = 1) {
|
|
86
|
+
Instance.InitFolder();
|
|
87
|
+
Instance.StartCoroutine(Instance.TakeCameraScreenshotCo(camera, fileName, superSampleSize));
|
|
104
88
|
}
|
|
105
89
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
rt = null;
|
|
112
|
-
|
|
113
|
-
if (shouldSaveCaptures) {
|
|
114
|
-
SaveScreenshot(fileName, superSampleSize, true);
|
|
115
|
-
}
|
|
90
|
+
public IEnumerator TakeCameraScreenshotCo(Camera camera, string fileName = "", int superSampleSize = 1) {
|
|
91
|
+
bool enabled = camera.enabled;
|
|
92
|
+
|
|
93
|
+
// Have to capture at end of frame for ScreenCapture to work
|
|
94
|
+
yield return new WaitForEndOfFrame();
|
|
116
95
|
|
|
117
|
-
|
|
118
|
-
|
|
96
|
+
try {
|
|
97
|
+
screenShot = new Texture2D(resWidth * superSampleSize, resHeight * superSampleSize, TextureFormat.RGB24, false);
|
|
98
|
+
rt = new RenderTexture(resWidth, resHeight, resDepth);
|
|
99
|
+
camera.enabled = true;
|
|
100
|
+
camera.targetTexture = rt;
|
|
101
|
+
camera.Render();
|
|
102
|
+
RenderTexture.active = rt;
|
|
103
|
+
} catch(Exception e) {
|
|
104
|
+
Debug.LogError("Error saving: " + e.Message);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Save the render textures data to a texture2D
|
|
108
|
+
screenShot.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
|
|
109
|
+
camera.targetTexture = null;
|
|
110
|
+
RenderTexture.active = null;
|
|
111
|
+
rt.Release();
|
|
112
|
+
rt = null;
|
|
113
|
+
|
|
114
|
+
if (shouldSaveCaptures) {
|
|
115
|
+
SaveScreenshot(fileName, superSampleSize, true);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if(onPictureTaken != null){
|
|
119
|
+
onPictureTaken(screenShot);
|
|
120
|
+
}
|
|
121
|
+
camera.enabled = enabled;
|
|
119
122
|
}
|
|
120
|
-
camera.enabled = enabled;
|
|
121
|
-
}
|
|
122
123
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
private void SaveScreenshot(string fileName, int superSampleSize, bool png) {
|
|
125
|
+
if (!screenShot || screenShot.width <= 0) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
SaveTexture(screenShot, fileName, png);
|
|
129
|
+
screenShot.Apply();
|
|
126
130
|
}
|
|
127
|
-
SaveTexture(screenShot, fileName, png);
|
|
128
|
-
screenShot.Apply();
|
|
129
|
-
}
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
public CameraScreenshotResponse SaveRenderTexture(RenderTexture rt, string fileName, bool png){
|
|
133
|
+
if(!rt){
|
|
134
|
+
return new CameraScreenshotResponse();
|
|
135
|
+
}
|
|
136
|
+
RenderTexture.active = rt;
|
|
137
|
+
var texture = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
|
|
138
|
+
texture.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
|
|
139
|
+
RenderTexture.active = null;
|
|
140
|
+
return SaveTexture(texture, fileName, png);
|
|
134
141
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
142
|
+
|
|
143
|
+
public CameraScreenshotResponse SaveTexture(Texture2D texture, string fileName, bool png){
|
|
144
|
+
try {
|
|
145
|
+
//Debug.Log("Saving Texture size: " + texture.width +", " + texture.height);
|
|
146
|
+
string filePath = string.IsNullOrEmpty(fileName)
|
|
147
|
+
? ScreenShotName(texture.width, texture.height, png)
|
|
148
|
+
: ScreenShotName(fileName, png);
|
|
149
|
+
byte[] bytes = png ? texture.EncodeToPNG() : texture.EncodeToJPG();
|
|
150
|
+
string directoryPath = Path.GetDirectoryName(filePath);
|
|
151
|
+
if(!Directory.Exists(directoryPath)){
|
|
152
|
+
Directory.CreateDirectory(directoryPath);
|
|
153
|
+
}
|
|
154
|
+
File.WriteAllBytes(filePath, bytes);
|
|
155
|
+
Debug.Log(string.Format("Saved screenshot to: {0}", filePath));
|
|
156
|
+
return new CameraScreenshotResponse(){filesize = bytes.Length, extension = Path.GetExtension(filePath), path = filePath};
|
|
157
|
+
} catch (Exception e) {
|
|
158
|
+
Debug.LogError("Error saving texture: " + e.Message);
|
|
152
159
|
}
|
|
153
|
-
|
|
154
|
-
Debug.Log(string.Format("Saved screenshot to: {0}", filePath));
|
|
155
|
-
return new CameraScreenshotResponse(){filesize = bytes.Length, extension = Path.GetExtension(filePath), path = filePath};
|
|
156
|
-
} catch (Exception e) {
|
|
157
|
-
Debug.LogError("Error saving texture: " + e.Message);
|
|
160
|
+
return new CameraScreenshotResponse();
|
|
158
161
|
}
|
|
159
|
-
|
|
160
|
-
}
|
|
162
|
+
}
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
|
|
@@ -9,6 +9,7 @@ namespace Code.Platform.Shared {
|
|
|
9
9
|
public static string dataStoreService = "https://data-store-service-fxy2zritya-uc.a.run.app";
|
|
10
10
|
public static string deploymentService = "https://deployment-service-fxy2zritya-uc.a.run.app";
|
|
11
11
|
public static string analyticsService = "https://analytics-service-fxy2zritya-uc.a.run.app";
|
|
12
|
+
public static string moderationService = "https://moderation-service-fxy2zritya-uc.a.run.app";
|
|
12
13
|
public static string gameCdn = "https://gcdn-staging.easy.gg";
|
|
13
14
|
public static string cdn = "https://cdn-staging.easy.gg";
|
|
14
15
|
public static string mainWeb = "https://staging.airship.gg";
|
|
@@ -20,6 +21,7 @@ namespace Code.Platform.Shared {
|
|
|
20
21
|
public static string dataStoreService = "https://api-staging.airship.gg/data-store";
|
|
21
22
|
public static string deploymentService = "https://api-staging.airship.gg/deployment";
|
|
22
23
|
public static string analyticsService = "https://api-staging.airship.gg/analytics";
|
|
24
|
+
public static string moderationService = "https://api-staging.airship.gg/moderation";
|
|
23
25
|
public static string gameCdn = "https://gcdn-staging.easy.gg";
|
|
24
26
|
public static string cdn = "https://cdn-staging.easy.gg";
|
|
25
27
|
public static string mainWeb = "https://staging.airship.gg";
|
|
@@ -33,6 +35,7 @@ namespace Code.Platform.Shared {
|
|
|
33
35
|
public static string dataStoreService = "https://data-store-service-hwcvz2epka-uc.a.run.app";
|
|
34
36
|
public static string deploymentService = "https://deployment-service-hwcvz2epka-uc.a.run.app";
|
|
35
37
|
public static string analyticsService = "https://analytics-service-hwcvz2epka-uc.a.run.app";
|
|
38
|
+
public static string moderationService = "https://moderation-service-hwcvz2epka-uc.a.run.app";
|
|
36
39
|
public static string cdn = "https://cdn.airship.gg";
|
|
37
40
|
public static string gameCdn = "https://gcdn.airship.gg";
|
|
38
41
|
public static string mainWeb = "https://airship.gg";
|
|
@@ -44,6 +47,7 @@ namespace Code.Platform.Shared {
|
|
|
44
47
|
public static string dataStoreService = "https://api.airship.gg/data-store";
|
|
45
48
|
public static string deploymentService = "https://api.airship.gg/deployment";
|
|
46
49
|
public static string analyticsService = "https://api.airship.gg/analytics";
|
|
50
|
+
public static string moderationService = "https://api.airship.gg/moderation";
|
|
47
51
|
public static string cdn = "https://cdn.airship.gg";
|
|
48
52
|
public static string gameCdn = "https://gcdn.airship.gg";
|
|
49
53
|
public static string mainWeb = "https://airship.gg";
|
|
@@ -89,6 +89,7 @@ namespace CsToTs.TypeScript {
|
|
|
89
89
|
// }
|
|
90
90
|
type.GetGenericArguments().ToList().ForEach(t => {
|
|
91
91
|
if (t.Name == type.Name) return;
|
|
92
|
+
if (t.Name == "InternalCameraScreenshotRecorder") return;
|
|
92
93
|
PopulateTypeDefinition(t, context);
|
|
93
94
|
});
|
|
94
95
|
type = type.GetGenericTypeDefinition();
|
|
@@ -138,7 +138,6 @@ public class TypeGenerator : MonoBehaviour
|
|
|
138
138
|
typeof(LayoutRebuilder),
|
|
139
139
|
typeof(RectTransformUtility),
|
|
140
140
|
typeof(ScrollRect),
|
|
141
|
-
typeof(InternalCameraScreenshotRecorder),
|
|
142
141
|
typeof(Ray),
|
|
143
142
|
typeof(MaterialPropertyBlock),
|
|
144
143
|
typeof(DevConsole),
|
|
@@ -259,6 +258,7 @@ public class TypeGenerator : MonoBehaviour
|
|
|
259
258
|
typeof(AirshipPredictionManager),
|
|
260
259
|
typeof(VisualGraphComponent),
|
|
261
260
|
typeof(AccessoryAddMode),
|
|
261
|
+
typeof(RectMask2D),
|
|
262
262
|
|
|
263
263
|
// Steam
|
|
264
264
|
typeof(AirshipSteamFriendInfo),
|
|
@@ -332,6 +332,7 @@ public class TypeGenerator : MonoBehaviour
|
|
|
332
332
|
"\\.MonoBehaviour$",
|
|
333
333
|
"\\.InternalCameraScreenshotRecorder$",
|
|
334
334
|
"\\.OcclusionCam$",
|
|
335
|
+
"\\.AirshipUniVoiceNetwork$"
|
|
335
336
|
};
|
|
336
337
|
|
|
337
338
|
var options = new TypeScriptOptions
|
|
@@ -35,8 +35,14 @@ namespace Code.VoiceChat {
|
|
|
35
35
|
public event Action<short, ChatroomAudioSegment> OnAudioReceived;
|
|
36
36
|
public event Action<ChatroomAudioSegment> OnAudioBroadcasted;
|
|
37
37
|
|
|
38
|
+
// connectionId (int), speakingLevel (float)
|
|
39
|
+
public event Action<object, object> onPlayerSpeakingLevel;
|
|
40
|
+
|
|
41
|
+
// speakingLevel (float)
|
|
42
|
+
public event Action<object> onLocalSpeakingLevel;
|
|
43
|
+
|
|
38
44
|
// Peer ID management
|
|
39
|
-
public short
|
|
45
|
+
public short LocalPeerId { get; private set; } = -1;
|
|
40
46
|
public List<short> PeerIDs { get; private set; } = new List<short>();
|
|
41
47
|
|
|
42
48
|
// UniVoice peer ID <-> FishNet connection ID mapping
|
|
@@ -47,6 +53,7 @@ namespace Code.VoiceChat {
|
|
|
47
53
|
|
|
48
54
|
private uint audioNonce = 0;
|
|
49
55
|
|
|
56
|
+
|
|
50
57
|
private void OnDisable() {
|
|
51
58
|
if (this.agent != null) {
|
|
52
59
|
this.agent.Dispose();
|
|
@@ -101,15 +108,15 @@ namespace Code.VoiceChat {
|
|
|
101
108
|
void OnDestroy() {
|
|
102
109
|
// If the client disconnects while own ID is -1, that means
|
|
103
110
|
// it haven't connected earlier and the connection attempt has failed.
|
|
104
|
-
if (
|
|
111
|
+
if (LocalPeerId == -1) {
|
|
105
112
|
OnChatroomJoinFailed?.Invoke(new Exception("Could not join chatroom"));
|
|
106
113
|
return;
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
// This method is *also* called on the server when the server is shutdown.
|
|
110
117
|
// So we check peer ID to ensure that we're running this only on a peer.
|
|
111
|
-
if (
|
|
112
|
-
|
|
118
|
+
if (LocalPeerId >= 0) {
|
|
119
|
+
LocalPeerId = -1;
|
|
113
120
|
PeerIDs.Clear();
|
|
114
121
|
peerIdToConnectionIdMap.Clear();
|
|
115
122
|
OnLeftChatroom?.Invoke();
|
|
@@ -124,8 +131,8 @@ namespace Code.VoiceChat {
|
|
|
124
131
|
this.Log($"Initialized self with PeerId {assignedPeerId} and peers: {string.Join(", ", existingPeers)}");
|
|
125
132
|
|
|
126
133
|
// Get self ID and fire that joined chatroom event
|
|
127
|
-
|
|
128
|
-
OnJoinedChatroom?.Invoke(
|
|
134
|
+
LocalPeerId = assignedPeerId;
|
|
135
|
+
OnJoinedChatroom?.Invoke(LocalPeerId);
|
|
129
136
|
|
|
130
137
|
for (int i = 0; i < existingPeers.Length; i++) {
|
|
131
138
|
this.peerIdToConnectionIdMap[existingPeers[i]] = existingPeerConnectionIds[i];
|
|
@@ -282,23 +289,58 @@ namespace Code.VoiceChat {
|
|
|
282
289
|
RpcSendAudioToClient(senderPeerId, bytes, this.audioNonce);
|
|
283
290
|
|
|
284
291
|
if (Application.isEditor) {
|
|
285
|
-
|
|
286
|
-
OnAudioReceived?.Invoke(senderPeerId, segment);
|
|
292
|
+
this.EmitAudioInScene(senderPeerId, bytes);
|
|
287
293
|
}
|
|
288
294
|
}
|
|
289
295
|
|
|
290
296
|
[ClientRpc(channel = Channels.Reliable)]
|
|
291
297
|
void RpcSendAudioToClient(short senderPeerId, byte[] bytes, uint nonce) {
|
|
292
298
|
// print($"[client] received audio from server for peer {senderPeerId}. Frame={Time.frameCount} Nonce={nonce}");
|
|
299
|
+
this.EmitAudioInScene(senderPeerId, bytes);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private void EmitAudioInScene(short senderPeerId, byte[] bytes) {
|
|
293
303
|
var segment = FromByteArray<ChatroomAudioSegment>(bytes);
|
|
304
|
+
|
|
305
|
+
if (senderPeerId == LocalPeerId && RunCore.IsClient() && NetworkClient.isConnected) {
|
|
306
|
+
// Local speaking
|
|
307
|
+
var speakingLevel = this.ComputeSpeakingLevel(segment.samples);
|
|
308
|
+
onLocalSpeakingLevel?.Invoke(speakingLevel);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
|
|
294
312
|
OnAudioReceived?.Invoke(senderPeerId, segment);
|
|
313
|
+
|
|
314
|
+
NetworkConnection connection = this.GetNetworkConnectionFromPeerId(senderPeerId);
|
|
315
|
+
if (connection != null) {
|
|
316
|
+
var speakingLevel = this.ComputeSpeakingLevel(segment.samples);
|
|
317
|
+
onPlayerSpeakingLevel?.Invoke(connection.connectionId, speakingLevel);
|
|
318
|
+
}
|
|
295
319
|
}
|
|
320
|
+
|
|
321
|
+
private float ComputeSpeakingLevel(float[] samples) {
|
|
322
|
+
float sum = 0f;
|
|
323
|
+
for (int i = 0; i < samples.Length; i++) {
|
|
324
|
+
sum += samples[i] * samples[i];
|
|
325
|
+
}
|
|
326
|
+
float rms = Mathf.Sqrt(sum / samples.Length);
|
|
327
|
+
return Mathf.Clamp01(rms * 10f); // scale up and clamp
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// public float GetSpeakingLevel(int connectionId) {
|
|
331
|
+
// if (this.playerConnectionIdToSpeakingLevelMap.TryGetValue(connectionId, out var speakingLevel)) {
|
|
332
|
+
// return speakingLevel;
|
|
333
|
+
// }
|
|
334
|
+
// return 0;
|
|
335
|
+
// }
|
|
296
336
|
|
|
297
337
|
public void BroadcastAudioSegment(ChatroomAudioSegment data) {
|
|
298
338
|
if (!NetworkClient.isConnected) return;
|
|
299
339
|
|
|
300
340
|
if (isClient) {
|
|
301
|
-
|
|
341
|
+
var bytes = ToByteArray(data);
|
|
342
|
+
this.EmitAudioInScene(LocalPeerId, bytes);
|
|
343
|
+
RpcSendAudioToServer(bytes);
|
|
302
344
|
}
|
|
303
345
|
|
|
304
346
|
OnAudioBroadcasted?.Invoke(data);
|
|
@@ -331,7 +373,6 @@ namespace Code.VoiceChat {
|
|
|
331
373
|
if (NetworkServer.connections.TryGetValue(peerIdToConnectionIdMap[peerId], out var connection)) {
|
|
332
374
|
return connection;
|
|
333
375
|
}
|
|
334
|
-
|
|
335
376
|
return null;
|
|
336
377
|
}
|
|
337
378
|
|