123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- using System;
- using System.Runtime.InteropServices;
- namespace ET
- {
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct IdStruct
- {
- public uint Time; // 30bit
- public int Process; // 18bit
- public ushort Value; // 16bit
- public long ToLong()
- {
- ulong result = 0;
- result |= this.Value;
- result |= (ulong) this.Process << 16;
- result |= (ulong) this.Time << 34;
- return (long) result;
- }
- public IdStruct(uint time, int process, ushort value)
- {
- this.Process = process;
- this.Time = time;
- this.Value = value;
- }
- public IdStruct(long id)
- {
- ulong result = (ulong) id;
- this.Value = (ushort) (result & ushort.MaxValue);
- result >>= 16;
- this.Process = (int) (result & IdGenerater.Mask18bit);
- result >>= 18;
- this.Time = (uint) result;
- }
- public override string ToString()
- {
- return $"process: {this.Process}, time: {this.Time}, value: {this.Value}";
- }
- }
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct InstanceIdStruct
- {
- public uint Time; // 当年开始的tick 28bit
- public int Process; // 18bit
- public uint Value; // 18bit
- public long ToLong()
- {
- ulong result = 0;
- result |= this.Value;
- result |= (ulong)this.Process << 18;
- result |= (ulong) this.Time << 36;
- return (long) result;
- }
- public InstanceIdStruct(long id)
- {
- ulong result = (ulong) id;
- this.Value = (uint)(result & IdGenerater.Mask18bit);
- result >>= 18;
- this.Process = (int)(result & IdGenerater.Mask18bit);
- result >>= 18;
- this.Time = (uint)result;
- }
- public InstanceIdStruct(uint time, int process, uint value)
- {
- this.Time = time;
- this.Process = process;
- this.Value = value;
- }
-
- // 给SceneId使用
- public InstanceIdStruct(int process, uint value)
- {
- this.Time = 0;
- this.Process = process;
- this.Value = value;
- }
- public override string ToString()
- {
- return $"process: {this.Process}, value: {this.Value} time: {this.Time}";
- }
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct UnitIdStruct
- {
- public uint Time; // 30bit 34年
- public ushort Zone; // 10bit 1024个区
- public byte ProcessMode; // 8bit Process % 256 一个区最多256个进程
- public ushort Value; // 16bit 每秒每个进程最大16K个Unit
- public long ToLong()
- {
- ulong result = 0;
- result |= this.Value;
- result |= (uint)this.ProcessMode << 16;
- result |= (ulong) this.Zone << 24;
- result |= (ulong) this.Time << 34;
- return (long) result;
- }
- public UnitIdStruct(int zone, int process, uint time, ushort value)
- {
- this.Time = time;
- this.ProcessMode = (byte)(process % 256);
- this.Value = value;
- this.Zone = (ushort)zone;
- }
-
- public UnitIdStruct(long id)
- {
- ulong result = (ulong) id;
- this.Value = (ushort)(result & ushort.MaxValue);
- result >>= 16;
- this.ProcessMode = (byte)(result & byte.MaxValue);
- result >>= 8;
- this.Zone = (ushort)(result & 0x03ff);
- result >>= 10;
- this.Time = (uint)result;
- }
-
- public override string ToString()
- {
- return $"ProcessMode: {this.ProcessMode}, value: {this.Value} time: {this.Time}";
- }
-
- public static int GetUnitZone(long unitId)
- {
- int v = (int) ((unitId >> 24) & 0x03ff); // 取出10bit
- return v;
- }
- }
- public class IdGenerater: Singleton<IdGenerater>
- {
- public const int Mask18bit = 0x03ffff;
- public const int MaxZone = 1024;
-
- private long epoch2020;
- private ushort value;
- private uint lastIdTime;
-
- private long epochThisYear;
- private uint instanceIdValue;
- private uint lastInstanceIdTime;
-
-
- private ushort unitIdValue;
- private uint lastUnitIdTime;
- public IdGenerater()
- {
- long epoch1970tick = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
- this.epoch2020 = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - epoch1970tick;
- this.epochThisYear = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - epoch1970tick;
-
- this.lastInstanceIdTime = TimeSinceThisYear();
- if (this.lastInstanceIdTime <= 0)
- {
- Log.Warning($"lastInstanceIdTime less than 0: {this.lastInstanceIdTime}");
- this.lastInstanceIdTime = 1;
- }
- this.lastIdTime = TimeSince2020();
- if (this.lastIdTime <= 0)
- {
- Log.Warning($"lastIdTime less than 0: {this.lastIdTime}");
- this.lastIdTime = 1;
- }
- this.lastUnitIdTime = TimeSince2020();
- if (this.lastUnitIdTime <= 0)
- {
- Log.Warning($"lastUnitIdTime less than 0: {this.lastUnitIdTime}");
- this.lastUnitIdTime = 1;
- }
- }
- private uint TimeSince2020()
- {
- uint a = (uint)((TimeInfo.Instance.FrameTime - this.epoch2020) / 1000);
- return a;
- }
-
- private uint TimeSinceThisYear()
- {
- uint a = (uint)((TimeInfo.Instance.FrameTime - this.epochThisYear) / 1000);
- return a;
- }
-
- public long GenerateInstanceId()
- {
- uint time = TimeSinceThisYear();
- if (time > this.lastInstanceIdTime)
- {
- this.lastInstanceIdTime = time;
- this.instanceIdValue = 0;
- }
- else
- {
- ++this.instanceIdValue;
-
- if (this.instanceIdValue > IdGenerater.Mask18bit - 1) // 18bit
- {
- ++this.lastInstanceIdTime; // 借用下一秒
- this.instanceIdValue = 0;
- Log.Error($"instanceid count per sec overflow: {time} {this.lastInstanceIdTime}");
- }
- }
- InstanceIdStruct instanceIdStruct = new InstanceIdStruct(this.lastInstanceIdTime, Options.Instance.Process, this.instanceIdValue);
- return instanceIdStruct.ToLong();
- }
- public long GenerateId()
- {
- uint time = TimeSince2020();
- if (time > this.lastIdTime)
- {
- this.lastIdTime = time;
- this.value = 0;
- }
- else
- {
- ++this.value;
-
- if (value > ushort.MaxValue - 1)
- {
- this.value = 0;
- ++this.lastIdTime; // 借用下一秒
- Log.Error($"id count per sec overflow: {time} {this.lastIdTime}");
- }
- }
-
- IdStruct idStruct = new IdStruct(this.lastIdTime, Options.Instance.Process, value);
- return idStruct.ToLong();
- }
-
- public long GenerateUnitId(int zone)
- {
- if (zone > MaxZone)
- {
- throw new Exception($"zone > MaxZone: {zone}");
- }
- uint time = TimeSince2020();
- if (time > this.lastUnitIdTime)
- {
- this.lastUnitIdTime = time;
- this.unitIdValue = 0;
- }
- else
- {
- ++this.unitIdValue;
-
- if (this.unitIdValue > ushort.MaxValue - 1)
- {
- this.unitIdValue = 0;
- ++this.lastUnitIdTime; // 借用下一秒
- Log.Error($"unitid count per sec overflow: {time} {this.lastUnitIdTime}");
- }
- }
- UnitIdStruct unitIdStruct = new UnitIdStruct(zone, Options.Instance.Process, this.lastUnitIdTime, this.unitIdValue);
- return unitIdStruct.ToLong();
- }
- }
- }
|