IdGenerater.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace ET
  4. {
  5. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  6. public struct IdStruct
  7. {
  8. public uint Time; // 30bit
  9. public int Process; // 18bit
  10. public ushort Value; // 16bit
  11. public long ToLong()
  12. {
  13. ulong result = 0;
  14. result |= this.Value;
  15. result |= (ulong) this.Process << 16;
  16. result |= (ulong) this.Time << 34;
  17. return (long) result;
  18. }
  19. public IdStruct(uint time, int process, ushort value)
  20. {
  21. this.Process = process;
  22. this.Time = time;
  23. this.Value = value;
  24. }
  25. public IdStruct(long id)
  26. {
  27. ulong result = (ulong) id;
  28. this.Value = (ushort) (result & ushort.MaxValue);
  29. result >>= 16;
  30. this.Process = (int) (result & IdGenerater.Mask18bit);
  31. result >>= 18;
  32. this.Time = (uint) result;
  33. }
  34. public override string ToString()
  35. {
  36. return $"process: {this.Process}, time: {this.Time}, value: {this.Value}";
  37. }
  38. }
  39. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  40. public struct InstanceIdStruct
  41. {
  42. public uint Time; // 当年开始的tick 28bit
  43. public int Process; // 18bit
  44. public uint Value; // 18bit
  45. public long ToLong()
  46. {
  47. ulong result = 0;
  48. result |= this.Value;
  49. result |= (ulong)this.Process << 18;
  50. result |= (ulong) this.Time << 36;
  51. return (long) result;
  52. }
  53. public InstanceIdStruct(long id)
  54. {
  55. ulong result = (ulong) id;
  56. this.Value = (uint)(result & IdGenerater.Mask18bit);
  57. result >>= 18;
  58. this.Process = (int)(result & IdGenerater.Mask18bit);
  59. result >>= 18;
  60. this.Time = (uint)result;
  61. }
  62. public InstanceIdStruct(uint time, int process, uint value)
  63. {
  64. this.Time = time;
  65. this.Process = process;
  66. this.Value = value;
  67. }
  68. // 给SceneId使用
  69. public InstanceIdStruct(int process, uint value)
  70. {
  71. this.Time = 0;
  72. this.Process = process;
  73. this.Value = value;
  74. }
  75. public override string ToString()
  76. {
  77. return $"process: {this.Process}, value: {this.Value} time: {this.Time}";
  78. }
  79. }
  80. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  81. public struct UnitIdStruct
  82. {
  83. public uint Time; // 30bit 34年
  84. public ushort Zone; // 10bit 1024个区
  85. public byte ProcessMode; // 8bit Process % 256 一个区最多256个进程
  86. public ushort Value; // 16bit 每秒每个进程最大16K个Unit
  87. public long ToLong()
  88. {
  89. ulong result = 0;
  90. result |= this.Value;
  91. result |= (uint)this.ProcessMode << 16;
  92. result |= (ulong) this.Zone << 24;
  93. result |= (ulong) this.Time << 34;
  94. return (long) result;
  95. }
  96. public UnitIdStruct(int zone, int process, uint time, ushort value)
  97. {
  98. this.Time = time;
  99. this.ProcessMode = (byte)(process % 256);
  100. this.Value = value;
  101. this.Zone = (ushort)zone;
  102. }
  103. public UnitIdStruct(long id)
  104. {
  105. ulong result = (ulong) id;
  106. this.Value = (ushort)(result & ushort.MaxValue);
  107. result >>= 16;
  108. this.ProcessMode = (byte)(result & byte.MaxValue);
  109. result >>= 8;
  110. this.Zone = (ushort)(result & 0x03ff);
  111. result >>= 10;
  112. this.Time = (uint)result;
  113. }
  114. public override string ToString()
  115. {
  116. return $"ProcessMode: {this.ProcessMode}, value: {this.Value} time: {this.Time}";
  117. }
  118. public static int GetUnitZone(long unitId)
  119. {
  120. int v = (int) ((unitId >> 24) & 0x03ff); // 取出10bit
  121. return v;
  122. }
  123. }
  124. public class IdGenerater: Singleton<IdGenerater>
  125. {
  126. public const int Mask18bit = 0x03ffff;
  127. public const int MaxZone = 1024;
  128. private long epoch2020;
  129. private ushort value;
  130. private uint lastIdTime;
  131. private long epochThisYear;
  132. private uint instanceIdValue;
  133. private uint lastInstanceIdTime;
  134. private ushort unitIdValue;
  135. private uint lastUnitIdTime;
  136. public IdGenerater()
  137. {
  138. long epoch1970tick = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
  139. this.epoch2020 = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - epoch1970tick;
  140. this.epochThisYear = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - epoch1970tick;
  141. this.lastInstanceIdTime = TimeSinceThisYear();
  142. if (this.lastInstanceIdTime <= 0)
  143. {
  144. Log.Warning($"lastInstanceIdTime less than 0: {this.lastInstanceIdTime}");
  145. this.lastInstanceIdTime = 1;
  146. }
  147. this.lastIdTime = TimeSince2020();
  148. if (this.lastIdTime <= 0)
  149. {
  150. Log.Warning($"lastIdTime less than 0: {this.lastIdTime}");
  151. this.lastIdTime = 1;
  152. }
  153. this.lastUnitIdTime = TimeSince2020();
  154. if (this.lastUnitIdTime <= 0)
  155. {
  156. Log.Warning($"lastUnitIdTime less than 0: {this.lastUnitIdTime}");
  157. this.lastUnitIdTime = 1;
  158. }
  159. }
  160. private uint TimeSince2020()
  161. {
  162. uint a = (uint)((TimeInfo.Instance.FrameTime - this.epoch2020) / 1000);
  163. return a;
  164. }
  165. private uint TimeSinceThisYear()
  166. {
  167. uint a = (uint)((TimeInfo.Instance.FrameTime - this.epochThisYear) / 1000);
  168. return a;
  169. }
  170. public long GenerateInstanceId()
  171. {
  172. uint time = TimeSinceThisYear();
  173. if (time > this.lastInstanceIdTime)
  174. {
  175. this.lastInstanceIdTime = time;
  176. this.instanceIdValue = 0;
  177. }
  178. else
  179. {
  180. ++this.instanceIdValue;
  181. if (this.instanceIdValue > IdGenerater.Mask18bit - 1) // 18bit
  182. {
  183. ++this.lastInstanceIdTime; // 借用下一秒
  184. this.instanceIdValue = 0;
  185. Log.Error($"instanceid count per sec overflow: {time} {this.lastInstanceIdTime}");
  186. }
  187. }
  188. InstanceIdStruct instanceIdStruct = new InstanceIdStruct(this.lastInstanceIdTime, Options.Instance.Process, this.instanceIdValue);
  189. return instanceIdStruct.ToLong();
  190. }
  191. public long GenerateId()
  192. {
  193. uint time = TimeSince2020();
  194. if (time > this.lastIdTime)
  195. {
  196. this.lastIdTime = time;
  197. this.value = 0;
  198. }
  199. else
  200. {
  201. ++this.value;
  202. if (value > ushort.MaxValue - 1)
  203. {
  204. this.value = 0;
  205. ++this.lastIdTime; // 借用下一秒
  206. Log.Error($"id count per sec overflow: {time} {this.lastIdTime}");
  207. }
  208. }
  209. IdStruct idStruct = new IdStruct(this.lastIdTime, Options.Instance.Process, value);
  210. return idStruct.ToLong();
  211. }
  212. public long GenerateUnitId(int zone)
  213. {
  214. if (zone > MaxZone)
  215. {
  216. throw new Exception($"zone > MaxZone: {zone}");
  217. }
  218. uint time = TimeSince2020();
  219. if (time > this.lastUnitIdTime)
  220. {
  221. this.lastUnitIdTime = time;
  222. this.unitIdValue = 0;
  223. }
  224. else
  225. {
  226. ++this.unitIdValue;
  227. if (this.unitIdValue > ushort.MaxValue - 1)
  228. {
  229. this.unitIdValue = 0;
  230. ++this.lastUnitIdTime; // 借用下一秒
  231. Log.Error($"unitid count per sec overflow: {time} {this.lastUnitIdTime}");
  232. }
  233. }
  234. UnitIdStruct unitIdStruct = new UnitIdStruct(zone, Options.Instance.Process, this.lastUnitIdTime, this.unitIdValue);
  235. return unitIdStruct.ToLong();
  236. }
  237. }
  238. }