gg.easy.airship 0.1.2164 → 0.1.2166

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 (26) hide show
  1. package/Runtime/Code/Analytics/ClientFolderUploader.cs +62 -31
  2. package/Runtime/Code/Bundles/AssetBridge.cs +1 -1
  3. package/Runtime/Code/Bundles/SystemRoot.cs +20 -15
  4. package/Runtime/Code/Luau/LuauCoreReflection.cs +1 -1
  5. package/Runtime/Code/Luau/ReflectionList.cs +1 -0
  6. package/Runtime/Code/LuauAPI/FrameTimingManagerAPI.cs +22 -2
  7. package/Runtime/Code/Player/PlayerInfo.cs +2 -2
  8. package/Runtime/Code/Player/PlayerManagerBridge.cs +1 -1
  9. package/Runtime/Code/Quality/QualityManager.cs +143 -0
  10. package/Runtime/Code/Quality/QualityManager.cs.meta +3 -0
  11. package/Runtime/Code/Quality.meta +3 -0
  12. package/Runtime/Code/Steam/SteamLuauAPI.cs +34 -31
  13. package/Runtime/Code/VoiceChat/AirshipUniVoiceNetwork.cs +7 -0
  14. package/Runtime/Code/VoxelWorld/Resources/SampleDerivative.hlsl +7 -0
  15. package/Runtime/Code/VoxelWorld/Resources/SampleDerivative.hlsl.meta +7 -0
  16. package/Runtime/Code/VoxelWorld/Resources/VoxelWorldAtlasURP.shadergraph +1442 -161
  17. package/Runtime/Code/VoxelWorld/Resources/VoxelWorldMatURP.mat +2 -2
  18. package/Runtime/Code/VoxelWorld/TexturePacker.cs +31 -24
  19. package/Runtime/Code/VoxelWorld/VoxelBlocks.cs +4 -4
  20. package/Runtime/Scenes/CoreScene.unity +380 -290
  21. package/ThirdParty/Graphy - Ultimate Stats Monitor/Runtime/Timings/G_TimingsGraph.cs +7 -6
  22. package/package.json +1 -2
  23. package/ThirdParty/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph +0 -12074
  24. package/ThirdParty/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta +0 -10
  25. package/ThirdParty/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph +0 -11759
  26. package/ThirdParty/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta +0 -10
@@ -1,4 +1,5 @@
1
1
  using System;
2
+ using System.Collections.Generic;
2
3
  using System.IO;
3
4
  using System.IO.Compression;
4
5
  using System.Threading.Tasks;
@@ -57,46 +58,71 @@ namespace Code.Analytics {
57
58
  }
58
59
 
59
60
  var playerLogFile = Path.Combine(path, "Player.log");
61
+ var tempCurPlayerLogFile = Path.Combine(path, "Player-cur.log");
60
62
  var playerPrevLogFile = Path.Combine(path, "Player-prev.log");
61
63
  var editorLogFile = Path.Combine(path, "Editor.log");
64
+ var tempCurEditorLogFile = Path.Combine(path, "Editor-cur.log");
62
65
  var editorPrevLogFile = Path.Combine(path, "Editor-prev.log");
63
66
 
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
- }
67
+ var logMessages = new List<string>();
73
68
 
74
- if (File.Exists(playerPrevLogFile)) {
75
- fileExists = true;
76
- Debug.Log("[ClientFolderUploader] Adding Player-prev.log");
77
- archive.CreateEntryFromFile(playerPrevLogFile, "Player-prev.log");
78
- }
69
+ Action printDebugLines = () => {
70
+ foreach (var message in logMessages) {
71
+ Debug.Log(message);
72
+ }
73
+ logMessages.Clear();
74
+ };
79
75
 
80
- if (File.Exists(editorLogFile)) {
81
- fileExists = true;
82
- Debug.Log("[ClientFolderUploader] Adding Editor.log");
83
- archive.CreateEntryFromFile(editorLogFile, "Editor.log");
84
- }
76
+ var cleanupFiles = new List<string>() {
77
+ zipPath,
78
+ };
85
79
 
86
- if (File.Exists(editorPrevLogFile)) {
87
- fileExists = true;
88
- Debug.Log("[ClientFolderUploader] Adding Editor-prev.log");
89
- archive.CreateEntryFromFile(editorPrevLogFile, "Editor-prev.log");
80
+ Debug.Log("[ClientFolderUploader] Creating zip archive");
81
+ try {
82
+ if (File.Exists(zipPath)) {
83
+ File.Delete(zipPath);
90
84
  }
91
-
92
- if (!fileExists) {
93
- return;
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
+ }
94
118
  }
119
+ } catch (Exception ex) {
120
+ printDebugLines();
121
+ Debug.LogError($"[ClientFolderUploader] Zip creation failed: {ex.Message}");
122
+ throw;
95
123
  }
96
- } catch (Exception ex) {
97
- Debug.LogError($"[ClientFolderUploader] Zip creation failed: {ex.Message}");
98
- throw;
99
- }
124
+
125
+ printDebugLines();
100
126
 
101
127
  var contentType = "application/zip";
102
128
  var contentLength = new FileInfo(zipPath).Length;
@@ -135,7 +161,12 @@ namespace Code.Analytics {
135
161
  },
136
162
  }, "");
137
163
 
138
- File.Delete(zipPath);
164
+ Debug.Log("[ClientFolderUploader] Deleting temporary files");
165
+ foreach (var file in cleanupFiles) {
166
+ if (File.Exists(file)) {
167
+ File.Delete(file);
168
+ }
169
+ }
139
170
  } catch (Exception ex) {
140
171
  Debug.LogError($"[ClientFolderUploader] Error during upload process: {ex.Message}");
141
172
  throw;
@@ -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
  }
@@ -44,7 +44,7 @@ public class PlayerInfo : NetworkBehaviour {
44
44
 
45
45
  private void InitVoiceChat() {
46
46
  var voiceChatGO = new GameObject(
47
- $"{this.username}_VoiceChatAudioSourceOutput");
47
+ $"{this.username}_VoiceChatAudioSource");
48
48
  this.voiceChatAudioSource = voiceChatGO.AddComponent<AudioSource>();
49
49
  voiceChatGO.transform.SetParent(this.transform);
50
50
  }
@@ -57,7 +57,7 @@ public class PlayerInfo : NetworkBehaviour {
57
57
  public override void OnStartClient() {
58
58
  base.OnStartClient();
59
59
 
60
- if (isClient) {
60
+ if (isClient && !RunCore.IsServer()) {
61
61
  this.InitVoiceChat();
62
62
  }
63
63
  }
@@ -189,7 +189,7 @@ namespace Code.Player {
189
189
  }
190
190
 
191
191
  /**
192
- * Client side logic for when a new client joins.
192
+ * Server side logic for when a new client joins.
193
193
  */
194
194
  private async void NetworkServer_OnConnected(NetworkConnectionToClient conn) {
195
195
  if (playerPrefab == null) {
@@ -0,0 +1,143 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using UnityEngine;
4
+
5
+ namespace Code.Quality {
6
+ // We should redo this to be a single core number for quality
7
+ // NOTE: must match FrameHealth in Airship.d.ts
8
+ public enum FrameHealth {
9
+ Ok = 0,
10
+ Unhealthy = 1,
11
+ }
12
+
13
+ public struct QualityReport {
14
+ public double gpuAvg;
15
+ public double cpuMainAvg;
16
+ public double cpuRenderAvg;
17
+
18
+ public int numFrames;
19
+ }
20
+
21
+ [LuauAPI(LuauContext.Game)]
22
+ public class QualityManager : Singleton<QualityManager> {
23
+ public static event Action<object, object> OnQualityCheck;
24
+
25
+ private const int SampleCount = 500;
26
+ /// <summary>
27
+ /// Time after starting that we'll run a quality check on the client. This
28
+ /// will be sent to game clients to allow them to configure quality based on
29
+ /// performance.
30
+ /// </summary>
31
+ private const float QualityCheckTimeSec = 15;
32
+ /// <summary>
33
+ /// We use this to determine GPU/CPU bound.
34
+ /// </summary>
35
+ private const int FrameTimingCount = 50;
36
+ private short[] _fps = new short[SampleCount];
37
+ private FrameTiming[] _frameTimings = new FrameTiming[FrameTimingCount];
38
+ private int currentQualityLevel = 5;
39
+
40
+ /// <summary>
41
+ /// FPS array is circular, this is the front index
42
+ /// </summary>
43
+ private int _fpsFront;
44
+ /// <summary>
45
+ /// True once we've first loaded all SampleCount samples into _fps
46
+ /// </summary>
47
+ private bool _fpsSamplesLoaded;
48
+ private float _nextQualityCheck;
49
+
50
+ /// <summary>
51
+ /// For now we only run the quality check once after 15 seconds.
52
+ /// </summary>
53
+ private bool _hasRunQualityCheck;
54
+
55
+ private void Awake() {
56
+ _nextQualityCheck = Time.unscaledTime + QualityCheckTimeSec;
57
+ }
58
+
59
+ private void Update() {
60
+ if (_hasRunQualityCheck) return;
61
+
62
+ FrameTimingManager.CaptureFrameTimings();
63
+
64
+ if (!_fpsSamplesLoaded && _fpsFront == SampleCount - 1) _fpsSamplesLoaded = true;
65
+ _fps[_fpsFront++ % SampleCount] = (short) (1d / Time.unscaledDeltaTime);
66
+
67
+ // Should we do a quality check?
68
+ if (Time.time > _nextQualityCheck) {
69
+ _hasRunQualityCheck = true;
70
+ DoQualityCheck();
71
+ _nextQualityCheck = Time.time + QualityCheckTimeSec;
72
+ }
73
+ }
74
+
75
+ private void DoQualityCheck() {
76
+ var targetFrameRate = Application.targetFrameRate;
77
+ if (targetFrameRate < 0 || targetFrameRate > Screen.currentResolution.refreshRateRatio.value)
78
+ targetFrameRate = (int) (1.0 / Screen.currentResolution.refreshRateRatio.value);
79
+
80
+ var currentFivePercent = GetPercentFps(0.05f);
81
+
82
+ var frameHealth = FrameHealth.Ok;
83
+ var avgFrameTimings = GetRecentAverageFrameTimings();
84
+
85
+ // If our 5% is lower than 80% of target we should drop quality
86
+ if (currentFivePercent < 0.80 * targetFrameRate) {
87
+ frameHealth = FrameHealth.Unhealthy;
88
+ }
89
+
90
+ OnQualityCheck?.Invoke(frameHealth, avgFrameTimings);
91
+ }
92
+
93
+ private QualityReport GetRecentAverageFrameTimings() {
94
+ if (!FrameTimingManager.IsFeatureEnabled()) return default;
95
+
96
+ var numLatestTimings = FrameTimingManager.GetLatestTimings(FrameTimingCount, _frameTimings);
97
+ if (numLatestTimings <= 0) return default;
98
+
99
+ var result = new QualityReport();
100
+ for (var i = 0; i < numLatestTimings; i++) {
101
+ result.cpuMainAvg += _frameTimings[i].cpuMainThreadFrameTime;
102
+ result.cpuRenderAvg += _frameTimings[i].cpuRenderThreadFrameTime;
103
+ result.gpuAvg += _frameTimings[i].gpuFrameTime;
104
+ }
105
+ result.cpuMainAvg /= numLatestTimings;
106
+ result.cpuRenderAvg /= numLatestTimings;
107
+ result.gpuAvg /= numLatestTimings;
108
+ result.numFrames = (int) numLatestTimings;
109
+ return result;
110
+ }
111
+
112
+ /// <summary>
113
+ /// Gets the slowest percent of frames and averages them.
114
+ /// </summary>
115
+ private double GetPercentFps(float percent) {
116
+ var percentSampleCount = (int) Mathf.Ceil(SampleCount * percent);
117
+
118
+ // Load the first N samples and keep samples sorted
119
+ var samples = new List<short>(_fps.AsSpan(0, percentSampleCount).ToArray());
120
+ samples.Sort();
121
+
122
+ for (var i = percentSampleCount; i < _fps.Length; i++) {
123
+ // If we're slower than the best FPS in samples, insert
124
+ var largestFpsSample = samples[^1];
125
+ var sample = _fps[i];
126
+ if (sample < largestFpsSample) {
127
+ var index = samples.BinarySearch(sample);
128
+ // Will return bitwise compliment if larger than list
129
+ if (index < 0) index = ~index;
130
+
131
+ samples.Insert(index, sample);
132
+ samples.RemoveAt(samples.Count - 1);
133
+ }
134
+ }
135
+
136
+ var fpsTotal = 0d;
137
+ foreach (var sample in samples) {
138
+ fpsTotal += sample;
139
+ }
140
+ return fpsTotal / samples.Count;
141
+ }
142
+ }
143
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 61605bf762a14bc2af51dd67d0c8b156
3
+ timeCreated: 1753829150
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 0c5e40dfbd834a72af5a2e16f55361f7
3
+ timeCreated: 1753829136
@@ -177,42 +177,45 @@ public class SteamLuauAPI : Singleton<SteamLuauAPI> {
177
177
  return success;
178
178
  }
179
179
 
180
- public static AirshipSteamFriendInfo[] GetSteamFriends() {
181
- Assert.IsTrue(SteamManager.Initialized, "Can't fetch friends: steam is not initialized.");
180
+ public static async Task<AirshipSteamFriendInfo[]> GetSteamFriends() {
181
+ Assert.IsTrue(SteamManager.Initialized, "Can't fetch friends: steam is not initialized.");
182
182
 
183
183
  #if !STEAMWORKS_NET
184
- return Array.Empty<AirshipSteamFriendInfo>();
184
+ return Task.FromResult(Array.Empty<AirshipSteamFriendInfo>());
185
185
  #else
186
- var friendCount = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate);
187
- var friendInfos = new AirshipSteamFriendInfo[friendCount];
188
- for (var i = 0; i < friendCount; i++) {
189
- var friendId = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate);
190
- var friendName = SteamFriends.GetFriendPersonaName(friendId);
191
- var personaState = SteamFriends.GetFriendPersonaState(friendId);
192
- SteamFriends.GetFriendGamePlayed(friendId, out var friendGameInfo);
193
-
194
- var friendInfoStruct = new AirshipSteamFriendInfo {
195
- steamId = friendId.m_SteamID,
196
- steamName = friendName
197
- };
198
-
199
- // Is friend playing Airship?
200
- if (friendGameInfo.m_gameID.m_GameID == SteamUtils.GetAppID().m_AppId) {
201
- friendInfoStruct.playingAirship = true;
202
- } else if (friendGameInfo.m_gameID.IsValid()) {
203
- friendInfoStruct.playingOtherGame = true;
186
+ return await Task.Run(() => {
187
+ var friendCount = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate);
188
+ var friendInfos = new AirshipSteamFriendInfo[friendCount];
189
+ for (var i = 0; i < friendCount; i++) {
190
+ var friendId = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate);
191
+ var friendName = SteamFriends.GetFriendPersonaName(friendId);
192
+ var personaState = SteamFriends.GetFriendPersonaState(friendId);
193
+ SteamFriends.GetFriendGamePlayed(friendId, out var friendGameInfo);
194
+
195
+ var friendInfoStruct = new AirshipSteamFriendInfo {
196
+ steamId = friendId.m_SteamID,
197
+ steamName = friendName
198
+ };
199
+
200
+ // Is friend playing Airship?
201
+ if (friendGameInfo.m_gameID.m_GameID == SteamUtils.GetAppID().m_AppId) {
202
+ friendInfoStruct.playingAirship = true;
203
+ } else if (friendGameInfo.m_gameID.IsValid()) {
204
+ friendInfoStruct.playingOtherGame = true;
205
+ }
206
+
207
+ // Check if online
208
+ if (personaState != EPersonaState.k_EPersonaStateOffline) {
209
+ friendInfoStruct.online = true;
210
+ }
211
+
212
+ friendInfos[i] = friendInfoStruct;
204
213
  }
205
214
 
206
- // Check if online
207
- if (personaState != EPersonaState.k_EPersonaStateOffline) {
208
- friendInfoStruct.online = true;
209
- }
210
-
211
- friendInfos[i] = friendInfoStruct;
212
- }
213
- return friendInfos;
214
- #endif
215
- }
215
+ return friendInfos;
216
+ });
217
+ #endif
218
+ }
216
219
 
217
220
  /// <summary>
218
221
  /// Can return null.
@@ -54,6 +54,7 @@ namespace Code.VoiceChat {
54
54
  public ChatroomAgent agent;
55
55
 
56
56
  private uint audioNonce = 0;
57
+ private bool deafened = false;
57
58
 
58
59
 
59
60
  private void OnDisable() {
@@ -327,6 +328,8 @@ namespace Code.VoiceChat {
327
328
  }
328
329
 
329
330
  private void EmitAudioInScene(short senderPeerId, byte[] bytes) {
331
+ if (this.deafened) return;
332
+
330
333
  var segment = FromByteArray<ChatroomAudioSegment>(bytes);
331
334
 
332
335
  this.PreProcessAudio(segment);
@@ -384,6 +387,10 @@ namespace Code.VoiceChat {
384
387
  }
385
388
  }
386
389
 
390
+ public void SetDeafened(bool deafened) {
391
+ this.deafened = deafened;
392
+ }
393
+
387
394
  /// <summary>
388
395
  /// Returns the UniVoice peer Id corresponding to a previously
389
396
  /// registered Mirror connection Id
@@ -0,0 +1,7 @@
1
+ void SampleWithDerivatives_float(UnityTexture2D tex, UnitySamplerState samplerState, float2 uv, float2 dx, float2 dy, out float4 color) {
2
+ // The lower our derivative scale the further out we'll see
3
+ // high quality mips. Because we use a texture atlas that can bleed this needs
4
+ // to be relatively low.
5
+ float derivativeScale = 0.05;
6
+ color = tex.SampleGrad(samplerState, uv, dx * derivativeScale, dy * derivativeScale);
7
+ }
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: b1f2efc6343734f73a6d29e146797303
3
+ ShaderIncludeImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant: