饭太稀

This commit is contained in:
bob
2025-06-30 10:51:37 +08:00
commit 8e45469c83
753 changed files with 87652 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Fantasy.Helper;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
namespace Fantasy.IdFactory
{
/// <summary>
/// 表示一个唯一实体的ID。
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct EntityIdStruct
{
// EntityId:39 + 16 + 18 = 64
// +-------------------+-----------------------------+------------------------------------+
// | time(30) 最大34年 | SceneId(16) 最多65535个Scene | sequence(18) 每秒每个进程能生产262143个
// +-------------------+-----------------------------+------------------------------------+
public uint Time { get; set; }
public uint SceneId { get; set; }
public uint Sequence { get; set; }
public const uint MaskSequence = 0x3FFFF;
public const uint MaskSceneId = 0xFFFF;
public const uint MaskTime = 0x3FFFFFFF;
/// <summary>
/// WorldEntityIdStruct如果超过下面参数的设定该ID会失效
/// </summary>
/// <param name="time">time不能超过1073741823</param>
/// <param name="sceneId">sceneId不能超过65535</param>
/// <param name="sequence">sequence不能超过262143</param>
public EntityIdStruct(uint time, uint sceneId, uint sequence)
{
// 因为都是在配置表里拿到参数、所以这个不做边界判定、能节省一点点性能。
Time = time;
SceneId = sceneId;
Sequence = sequence;
}
public static implicit operator long(EntityIdStruct entityIdStruct)
{
ulong result = 0;
result |= entityIdStruct.Sequence;
result |= (ulong)entityIdStruct.SceneId << 18;
result |= (ulong)entityIdStruct.Time << 34;
return (long)result;
}
public static implicit operator EntityIdStruct(long entityId)
{
var result = (ulong) entityId;
var entityIdStruct = new EntityIdStruct
{
Sequence = (uint)(result & MaskSequence)
};
result >>= 18;
entityIdStruct.SceneId = (uint)(result & MaskSceneId);
result >>= 16;
entityIdStruct.Time = (uint)(result & MaskTime);
return entityIdStruct;
}
}
public sealed class EntityIdFactory : IEntityIdFactory
{
private readonly ushort _sceneId;
private uint _lastTime;
private uint _lastSequence;
private static readonly long Epoch1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
private static readonly long EpochThisYear = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - Epoch1970;
private EntityIdFactory() { }
public EntityIdFactory(uint sceneId)
{
switch (sceneId)
{
case > 65535:
{
throw new NotSupportedException($"sceneId:{sceneId} cannot be greater than 255255");
}
default:
{
_sceneId = (ushort)sceneId;
break;
}
}
}
public long Create
{
get
{
var time = (uint)((TimeHelper.Now - EpochThisYear) / 1000);
if (time > _lastTime)
{
_lastTime = time;
_lastSequence = 0;
}
else if (++_lastSequence > EntityIdStruct.MaskSequence - 1)
{
_lastTime++;
_lastSequence = 0;
}
return new EntityIdStruct(time, _sceneId, _lastSequence);
}
}
}
public sealed class EntityIdFactoryTool : IIdFactoryTool
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetTime(ref long entityId)
{
var result = (ulong)entityId >> 34;
return (uint)(result & EntityIdStruct.MaskTime);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetSceneId(ref long entityId)
{
var result = (ulong)entityId >> 18;
return (uint)(result & EntityIdStruct.MaskSceneId);
}
public byte GetWorldId(ref long entityId)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,137 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Fantasy.Helper;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
namespace Fantasy.IdFactory
{
/// <summary>
/// 表示一个运行时的ID。
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RuntimeIdStruct
{
// RuntimeId:23 + 8 + 8 + 25 = 64
// +-------------------+-----------------------------+--------------------------------------+
// | time(23) 最大60天 | SceneId(16) 最多65535个Scene | sequence(25) 每秒每个进程能生产33554431个
// +-------------------+-----------------------------+--------------------------------------+
public uint Time { get; private set; }
public uint SceneId { get; private set; }
public uint Sequence { get; private set; }
public const uint MaskSequence = 0x1FFFFFF;
public const uint MaskSceneId = 0xFFFF;
public const uint MaskTime = 0x7FFFFF;
/// <summary>
/// RuntimeIdStruct如果超过下面参数的设定该ID会失效
/// </summary>
/// <param name="time">time不能超过8388607</param>
/// <param name="sceneId">sceneId不能超过65535</param>
/// <param name="sequence">sequence不能超过33554431</param>
public RuntimeIdStruct(uint time, uint sceneId, uint sequence)
{
// 因为都是在配置表里拿到参数、所以这个不做边界判定、能节省一点点性能。
Time = time;
SceneId = sceneId;
Sequence = sequence;
}
public static implicit operator long(RuntimeIdStruct runtimeIdStruct)
{
ulong result = runtimeIdStruct.Sequence;
result |= (ulong)runtimeIdStruct.SceneId << 25;
result |= (ulong)runtimeIdStruct.Time << 41;
return (long)result;
}
public static implicit operator RuntimeIdStruct(long runtimeId)
{
var result = (ulong)runtimeId;
var runtimeIdStruct = new RuntimeIdStruct
{
Sequence = (uint)(result & MaskSequence)
};
result >>= 25;
runtimeIdStruct.SceneId = (byte)(result & MaskSceneId);
result >>= 16;
runtimeIdStruct.Time = (uint)(result & MaskTime);
return runtimeIdStruct;
}
}
public sealed class RuntimeIdFactory : IRuntimeIdFactory
{
private readonly uint _sceneId;
private uint _lastTime;
private uint _lastSequence;
private readonly long _epochNow;
private readonly long _epoch1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
private RuntimeIdFactory() { }
public RuntimeIdFactory(uint sceneId) : this(TimeHelper.Now, sceneId) { }
public RuntimeIdFactory(long epochNow, uint sceneId)
{
switch (sceneId)
{
case > 65535:
{
throw new NotSupportedException($"sceneId:{sceneId} cannot be greater than 255255");
}
default:
{
_sceneId = (ushort)sceneId;
_epochNow = epochNow - _epoch1970;
break;
}
}
}
public long Create
{
get
{
var time = (uint)((TimeHelper.Now - _epochNow) / 1000);
if (time > _lastTime)
{
_lastTime = time;
_lastSequence = 0;
}
else if (++_lastSequence > RuntimeIdStruct.MaskSequence - 1)
{
_lastTime++;
_lastSequence = 0;
}
return new RuntimeIdStruct(time, _sceneId, _lastSequence);
}
}
}
public sealed class RuntimeIdFactoryTool : IIdFactoryTool
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetTime(ref long runtimeId)
{
var result = (ulong)runtimeId >> 41;
return (uint)(result & RuntimeIdStruct.MaskTime);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetSceneId(ref long runtimeId)
{
var result = (ulong)runtimeId >> 25;
return (uint)(result & RuntimeIdStruct.MaskSceneId);
}
public byte GetWorldId(ref long entityId)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,132 @@
using System;
using System.Runtime.CompilerServices;
using Fantasy.Helper;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
namespace Fantasy.IdFactory
{
/// <summary>
/// Id生成器帮助类
/// </summary>
public static class IdFactoryHelper
{
private static IdFactoryType _idFactoryType = IdFactoryType.World;
/// <summary>
/// EntityId工具
/// </summary>
public static IIdFactoryTool EntityIdTool { get; private set; } = new WorldEntityIdFactoryTool();
/// <summary>
/// RuntimeId工具
/// </summary>
public static IIdFactoryTool RuntimeIdTool { get; private set; } = new WorldRuntimeIdFactoryTool();
/// <summary>
/// 初始化
/// </summary>
/// <param name="idFactoryType"></param>
public static void Initialize(IdFactoryType idFactoryType)
{
_idFactoryType = idFactoryType;
switch (_idFactoryType)
{
case IdFactoryType.Default:
{
EntityIdTool = new EntityIdFactoryTool();
RuntimeIdTool = new RuntimeIdFactoryTool();
return;
}
case IdFactoryType.World:
{
EntityIdTool = new WorldEntityIdFactoryTool();
RuntimeIdTool = new WorldRuntimeIdFactoryTool();
return;
}
}
}
internal static IEntityIdFactory EntityIdFactory(uint sceneId, byte worldId)
{
switch (_idFactoryType)
{
case IdFactoryType.Default:
{
return new EntityIdFactory(sceneId);
}
case IdFactoryType.World:
{
return new WorldEntityIdFactory(sceneId, worldId);
}
default:
{
throw new NotSupportedException($"IdFactoryType {_idFactoryType} is not supported.");
}
}
}
internal static IRuntimeIdFactory RuntimeIdFactory(long epochNow, uint sceneId, byte worldId)
{
switch (_idFactoryType)
{
case IdFactoryType.Default:
{
return new RuntimeIdFactory(sceneId);
}
case IdFactoryType.World:
{
if (epochNow == 0)
{
epochNow = TimeHelper.Now;
}
return new WorldRuntimeIdFactory(epochNow, sceneId, worldId);
}
default:
{
throw new NotSupportedException($"IdFactoryType {_idFactoryType} is not supported.");
}
}
}
internal static long EntityId(uint time, uint sceneId, byte wordId, uint sequence)
{
switch (_idFactoryType)
{
case IdFactoryType.Default:
{
return new EntityIdStruct(time, sceneId, sequence);
}
case IdFactoryType.World:
{
return new WorldEntityIdStruct(time, sceneId, wordId, sequence);
}
default:
{
throw new NotSupportedException($"IdFactoryType {_idFactoryType} is not supported.");
}
}
}
internal static long RuntimeId(uint time, uint sceneId, byte wordId, uint sequence)
{
switch (_idFactoryType)
{
case IdFactoryType.Default:
{
return new RuntimeIdStruct(time, sceneId, sequence);
}
case IdFactoryType.World:
{
return new WorldRuntimeIdStruct(time, sceneId, wordId, sequence);
}
default:
{
throw new NotSupportedException($"IdFactoryType {_idFactoryType} is not supported.");
}
}
}
}
}

View File

@@ -0,0 +1,23 @@
namespace Fantasy.IdFactory
{
/// <summary>
/// ID生成器规则
/// </summary>
public enum IdFactoryType
{
/// <summary>
/// 空。
/// </summary>
None = 0,
/// <summary>
/// 默认生成器
/// Scene最大为65535个。
/// </summary>
Default = 1,
/// <summary>
/// ID中包含World,使用这种方式可以不用管理合区的ID重复的问题。
/// 但Scene的数量也会限制到255个。
/// </summary>
World = 2
}
}

View File

@@ -0,0 +1,24 @@
namespace Fantasy.IdFactory
{
/// <summary>
/// EntityId生成器接口类
/// </summary>
public interface IEntityIdFactory
{
/// <summary>
/// 创建一个新的Id
/// </summary>
public long Create { get; }
}
/// <summary>
/// RuntimeId生成器接口类
/// </summary>
public interface IRuntimeIdFactory
{
/// <summary>
/// 创建一个新的Id
/// </summary>
public long Create { get; }
}
}

View File

@@ -0,0 +1,27 @@
namespace Fantasy.IdFactory
{
/// <summary>
/// Id扩展工具接口
/// </summary>
public interface IIdFactoryTool
{
/// <summary>
/// 获得创建时间
/// </summary>
/// <param name="entityId"></param>
/// <returns></returns>
public uint GetTime(ref long entityId);
/// <summary>
/// 获得SceneId
/// </summary>
/// <param name="entityId"></param>
/// <returns></returns>
public uint GetSceneId(ref long entityId);
/// <summary>
/// 获得WorldId
/// </summary>
/// <param name="entityId"></param>
/// <returns></returns>
public byte GetWorldId(ref long entityId);
}
}

View File

@@ -0,0 +1,153 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Fantasy.Helper;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
namespace Fantasy.IdFactory
{
/// <summary>
/// 表示一个唯一实体的ID。
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WorldEntityIdStruct
{
// EntityId:39 + 8 + 8 + 18 = 64
// +-------------------+--------------------------+-----------------------+------------------------------------+
// | time(30) 最大34年 | SceneId(8) 最多255个Scene | WordId(8) 最多255个世界 | sequence(18) 每秒每个进程能生产262143个
// +-------------------+--------------------------+-----------------------+------------------------------------+
public uint Time { get; private set; }
public uint SceneId { get; private set; }
public byte WordId { get; private set; }
public uint Sequence { get; private set; }
public const uint MaskSequence = 0x3FFFF;
public const uint MaskSceneId = 0xFF;
public const uint MaskWordId = 0xFF;
public const uint MaskTime = 0x3FFFFFFF;
/// <summary>
/// WorldEntityIdStruct如果超过下面参数的设定该ID会失效
/// </summary>
/// <param name="time">time不能超过1073741823</param>
/// <param name="sceneId">sceneId不能超过255</param>
/// <param name="wordId">wordId不能超过255</param>
/// <param name="sequence">sequence不能超过262143</param>
public WorldEntityIdStruct(uint time, uint sceneId, byte wordId, uint sequence)
{
// 因为都是在配置表里拿到参数、所以这个不做边界判定、能节省一点点性能。
Time = time;
SceneId = sceneId;
WordId = wordId;
Sequence = sequence;
}
public static implicit operator long(WorldEntityIdStruct entityIdStruct)
{
ulong result = 0;
result |= entityIdStruct.Sequence;
result |= (ulong)entityIdStruct.WordId << 18;
result |= (ulong)(entityIdStruct.SceneId % (entityIdStruct.WordId * 1000)) << 26;
result |= (ulong)entityIdStruct.Time << 34;
return (long)result;
}
public static implicit operator WorldEntityIdStruct(long entityId)
{
var result = (ulong) entityId;
var entityIdStruct = new WorldEntityIdStruct
{
Sequence = (uint)(result & MaskSequence)
};
result >>= 18;
entityIdStruct.WordId = (byte)(result & MaskWordId);
result >>= 8;
entityIdStruct.SceneId = (uint)(result & MaskSceneId) + (uint)entityIdStruct.WordId * 1000;
result >>= 8;
entityIdStruct.Time = (uint)(result & MaskTime);
return entityIdStruct;
}
}
public sealed class WorldEntityIdFactory : IEntityIdFactory
{
private readonly uint _sceneId;
private readonly byte _worldId;
private uint _lastTime;
private uint _lastSequence;
private static readonly long Epoch1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
private static readonly long EpochThisYear = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - Epoch1970;
private WorldEntityIdFactory() { }
public WorldEntityIdFactory(uint sceneId, byte worldId)
{
switch (sceneId)
{
case > 255255:
{
throw new NotSupportedException($"sceneId:{sceneId} cannot be greater than 255255");
}
case < 1001:
{
throw new NotSupportedException($"sceneId:{sceneId} cannot be less than 1001");
}
default:
{
_sceneId = sceneId;
_worldId = worldId;
break;
}
}
}
public long Create
{
get
{
var time = (uint)((TimeHelper.Now - EpochThisYear) / 1000);
if (time > _lastTime)
{
_lastTime = time;
_lastSequence = 0;
}
else if (++_lastSequence > WorldEntityIdStruct.MaskSequence - 1)
{
_lastTime++;
_lastSequence = 0;
}
return new WorldEntityIdStruct(time, _sceneId, _worldId, _lastSequence);
}
}
}
public sealed class WorldEntityIdFactoryTool : IIdFactoryTool
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetTime(ref long entityId)
{
var result = (ulong)entityId >> 34;
return (uint)(result & WorldEntityIdStruct.MaskTime);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetSceneId(ref long entityId)
{
var result = (ulong)entityId >> 18;
var worldId = (uint)(result & WorldEntityIdStruct.MaskWordId) * 1000;
result >>= 8;
return (uint)(result & WorldEntityIdStruct.MaskSceneId) + worldId;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte GetWorldId(ref long entityId)
{
var result = (ulong)entityId >> 18;
return (byte)(result & WorldEntityIdStruct.MaskWordId);
}
}
}

View File

@@ -0,0 +1,155 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Fantasy.Helper;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
namespace Fantasy.IdFactory
{
/// <summary>
/// 表示一个运行时的ID。
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WorldRuntimeIdStruct
{
// RuntimeId:23 + 8 + 8 + 25 = 64
// +-------------------+--------------------------+-----------------------+--------------------------------------+
// | time(23) 最大60天 | SceneId(8) 最多255个Scene | WordId(8) 最多255个世界 | sequence(25) 每秒每个进程能生产33554431个
// +-------------------+--------------------------+-----------------------+--------------------------------------+
public uint Time { get; private set; }
public uint SceneId { get; private set; }
public byte WordId { get; private set; }
public uint Sequence { get; private set; }
public const uint MaskSequence = 0x1FFFFFF;
public const uint MaskSceneId = 0xFF;
public const uint MaskWordId = 0xFF;
public const uint MaskTime = 0x7FFFFF;
/// <summary>
/// WorldRuntimeIdStruct如果超过下面参数的设定该ID会失效
/// </summary>
/// <param name="time">time不能超过8388607</param>
/// <param name="sceneId">sceneId不能超过255</param>
/// <param name="wordId">wordId不能超过255</param>
/// <param name="sequence">sequence不能超过33554431</param>
public WorldRuntimeIdStruct(uint time, uint sceneId, byte wordId, uint sequence)
{
// 因为都是在配置表里拿到参数、所以这个不做边界判定、能节省一点点性能。
Time = time;
SceneId = sceneId;
WordId = wordId;
Sequence = sequence;
}
public static implicit operator long(WorldRuntimeIdStruct runtimeIdStruct)
{
ulong result = runtimeIdStruct.Sequence;
result |= (ulong)runtimeIdStruct.WordId << 25;
result |= (ulong)(runtimeIdStruct.SceneId % (runtimeIdStruct.WordId * 1000)) << 33;
result |= (ulong)runtimeIdStruct.Time << 41;
return (long)result;
}
public static implicit operator WorldRuntimeIdStruct(long runtimeId)
{
var result = (ulong)runtimeId;
var runtimeIdStruct = new WorldRuntimeIdStruct
{
Sequence = (uint)(result & MaskSequence)
};
result >>= 25;
runtimeIdStruct.WordId = (byte)(result & MaskWordId);
result >>= 8;
runtimeIdStruct.SceneId = (uint)(result & MaskSceneId) + (uint)runtimeIdStruct.WordId * 1000;
result >>= 8;
runtimeIdStruct.Time = (uint)(result & MaskTime);
return runtimeIdStruct;
}
}
public sealed class WorldRuntimeIdFactory : IRuntimeIdFactory
{
private readonly uint _sceneId;
private readonly byte _worldId;
private uint _lastTime;
private uint _lastSequence;
private readonly long _epochNow;
private readonly long _epoch1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
private WorldRuntimeIdFactory() { }
public WorldRuntimeIdFactory(uint sceneId, byte worldId) : this(TimeHelper.Now, sceneId, worldId) { }
public WorldRuntimeIdFactory(long epochNow, uint sceneId, byte worldId)
{
switch (sceneId)
{
case > 255255:
{
throw new NotSupportedException($"sceneId:{sceneId} cannot be greater than 255255");
}
case < 1001:
{
throw new NotSupportedException($"sceneId:{sceneId} cannot be less than 1001");
}
default:
{
_sceneId = sceneId;
_worldId = worldId;
_epochNow = epochNow - _epoch1970;
break;
}
}
}
public long Create
{
get
{
var time = (uint)((TimeHelper.Now - _epochNow) / 1000);
if (time > _lastTime)
{
_lastTime = time;
_lastSequence = 0;
}
else if (++_lastSequence > WorldRuntimeIdStruct.MaskSequence - 1)
{
_lastTime++;
_lastSequence = 0;
}
return new WorldRuntimeIdStruct(time, _sceneId, _worldId, _lastSequence);
}
}
}
public sealed class WorldRuntimeIdFactoryTool : IIdFactoryTool
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetTime(ref long runtimeId)
{
var result = (ulong)runtimeId >> 41;
return (uint)(result & WorldRuntimeIdStruct.MaskTime);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetSceneId(ref long runtimeId)
{
var result = (ulong)runtimeId >> 25;
var worldId = (uint)(result & WorldRuntimeIdStruct.MaskWordId) * 1000;
result >>= 8;
return (uint)(result & WorldRuntimeIdStruct.MaskSceneId) + worldId;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte GetWorldId(ref long runtimeId)
{
var result = (ulong)runtimeId >> 25;
return (byte)(result & WorldRuntimeIdStruct.MaskWordId);
}
}
}