Utils.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Security.Cryptography;
  4. using UnityEngine;
  5. namespace Mirror
  6. {
  7. // Handles network messages on client and server
  8. public delegate void NetworkMessageDelegate(NetworkConnection conn, NetworkReader reader, int channelId);
  9. // Handles requests to spawn objects on the client
  10. public delegate GameObject SpawnDelegate(Vector3 position, uint assetId);
  11. public delegate GameObject SpawnHandlerDelegate(SpawnMessage msg);
  12. // Handles requests to unspawn objects on the client
  13. public delegate void UnSpawnDelegate(GameObject spawned);
  14. // channels are const ints instead of an enum so people can add their own
  15. // channels (can't extend an enum otherwise).
  16. //
  17. // note that Mirror is slowly moving towards quake style networking which
  18. // will only require reliable for handshake, and unreliable for the rest.
  19. // so eventually we can change this to an Enum and transports shouldn't
  20. // add custom channels anymore.
  21. public static class Channels
  22. {
  23. public const int Reliable = 0; // ordered
  24. public const int Unreliable = 1; // unordered
  25. }
  26. public static class Utils
  27. {
  28. public static uint GetTrueRandomUInt()
  29. {
  30. // use Crypto RNG to avoid having time based duplicates
  31. using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
  32. {
  33. byte[] bytes = new byte[4];
  34. rng.GetBytes(bytes);
  35. return BitConverter.ToUInt32(bytes, 0);
  36. }
  37. }
  38. public static bool IsPrefab(GameObject obj)
  39. {
  40. #if UNITY_EDITOR
  41. return UnityEditor.PrefabUtility.IsPartOfPrefabAsset(obj);
  42. #else
  43. return false;
  44. #endif
  45. }
  46. // simplified IsSceneObject check from Mirror II
  47. public static bool IsSceneObject(NetworkIdentity identity)
  48. {
  49. // original UNET / Mirror still had the IsPersistent check.
  50. // it never fires though. even for Prefabs dragged to the Scene.
  51. // (see Scene Objects example scene.)
  52. // #if UNITY_EDITOR
  53. // if (UnityEditor.EditorUtility.IsPersistent(identity.gameObject))
  54. // return false;
  55. // #endif
  56. return identity.gameObject.hideFlags != HideFlags.NotEditable &&
  57. identity.gameObject.hideFlags != HideFlags.HideAndDontSave &&
  58. identity.sceneId != 0;
  59. }
  60. public static bool IsSceneObjectWithPrefabParent(GameObject gameObject, out GameObject prefab)
  61. {
  62. prefab = null;
  63. #if UNITY_EDITOR
  64. if (!UnityEditor.PrefabUtility.IsPartOfPrefabInstance(gameObject))
  65. {
  66. return false;
  67. }
  68. prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(gameObject);
  69. #endif
  70. if (prefab == null)
  71. {
  72. Debug.LogError($"Failed to find prefab parent for scene object [name:{gameObject.name}]");
  73. return false;
  74. }
  75. return true;
  76. }
  77. // is a 2D point in screen? (from ummorpg)
  78. // (if width = 1024, then indices from 0..1023 are valid (=1024 indices)
  79. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  80. public static bool IsPointInScreen(Vector2 point) =>
  81. 0 <= point.x && point.x < Screen.width &&
  82. 0 <= point.y && point.y < Screen.height;
  83. // pretty print bytes as KB/MB/GB/etc. from DOTSNET
  84. // long to support > 2GB
  85. // divides by floats to return "2.5MB" etc.
  86. public static string PrettyBytes(long bytes)
  87. {
  88. // bytes
  89. if (bytes < 1024)
  90. return $"{bytes} B";
  91. // kilobytes
  92. else if (bytes < 1024L * 1024L)
  93. return $"{(bytes / 1024f):F2} KB";
  94. // megabytes
  95. else if (bytes < 1024 * 1024L * 1024L)
  96. return $"{(bytes / (1024f * 1024f)):F2} MB";
  97. // gigabytes
  98. return $"{(bytes / (1024f * 1024f * 1024f)):F2} GB";
  99. }
  100. // pretty print seconds as hours:minutes:seconds(.milliseconds/100)s.
  101. // double for long running servers.
  102. public static string PrettySeconds(double seconds)
  103. {
  104. TimeSpan t = TimeSpan.FromSeconds(seconds);
  105. string res = "";
  106. if (t.Days > 0) res += $"{t.Days}d";
  107. if (t.Hours > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Hours}h";
  108. if (t.Minutes > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Minutes}m";
  109. // 0.5s, 1.5s etc. if any milliseconds. 1s, 2s etc. if any seconds
  110. if (t.Milliseconds > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Seconds}.{(t.Milliseconds / 100)}s";
  111. else if (t.Seconds > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Seconds}s";
  112. // if the string is still empty because the value was '0', then at least
  113. // return the seconds instead of returning an empty string
  114. return res != "" ? res : "0s";
  115. }
  116. // universal .spawned function
  117. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  118. public static NetworkIdentity GetSpawnedInServerOrClient(uint netId)
  119. {
  120. // server / host mode: use the one from server.
  121. // host mode has access to all spawned.
  122. if (NetworkServer.active)
  123. {
  124. NetworkServer.spawned.TryGetValue(netId, out NetworkIdentity entry);
  125. return entry;
  126. }
  127. // client
  128. if (NetworkClient.active)
  129. {
  130. NetworkClient.spawned.TryGetValue(netId, out NetworkIdentity entry);
  131. return entry;
  132. }
  133. return null;
  134. }
  135. // keep a GUI window in screen.
  136. // for example. if it's at x=1000 and screen is resized to w=500,
  137. // it won't get lost in the invisible area etc.
  138. public static Rect KeepInScreen(Rect rect)
  139. {
  140. // ensure min
  141. rect.x = Math.Max(rect.x, 0);
  142. rect.y = Math.Max(rect.y, 0);
  143. // ensure max
  144. rect.x = Math.Min(rect.x, Screen.width - rect.width);
  145. rect.y = Math.Min(rect.y, Screen.width - rect.height);
  146. return rect;
  147. }
  148. }
  149. }