diff --git a/Config/NetworkProtocol/Inner/InnerMessage.proto b/Config/NetworkProtocol/Inner/InnerMessage.proto
index fad5279..feb5e4f 100644
--- a/Config/NetworkProtocol/Inner/InnerMessage.proto
+++ b/Config/NetworkProtocol/Inner/InnerMessage.proto
@@ -59,7 +59,7 @@ message G2Map_EnterMapRequest // IRouteRequest,Map2G_EnterMapResponse
{
string RoomCode = 1; //房间代码
int64 AccountId = 2; //账号id
- int32 MapId =3; //地图id
+ int32 MapId = 3; //地图id
}
/// 请求进入房间响应
@@ -67,7 +67,7 @@ message Map2G_EnterMapResponse // IRouteResponse
{
string RoomCode = 1; //房间代码
int32 MapId = 2; //地图id
- repeated MapUnitInfo Units = 2; //房间玩家列表
+ repeated MapUnitInfo Units = 3; //房间玩家列表
}
diff --git a/Config/NetworkProtocol/Outer/data/CommonProtoData.proto b/Config/NetworkProtocol/Outer/data/CommonProtoData.proto
index 5a4ce7f..83614ef 100644
--- a/Config/NetworkProtocol/Outer/data/CommonProtoData.proto
+++ b/Config/NetworkProtocol/Outer/data/CommonProtoData.proto
@@ -86,7 +86,7 @@ message FishInfo
{
uint32 ConfigId = 1; //配置id
int64 Id = 2; //物品id
- int32 Weight =3; //重量
+ int32 Weight = 3; //重量
int64 GetTime = 4; //获得时间
int64 ExpirationTime = 5; //失效时间
}
diff --git a/Entity/AssemblyHelper.cs b/Entity/AssemblyHelper.cs
index ae347d3..d9696d4 100644
--- a/Entity/AssemblyHelper.cs
+++ b/Entity/AssemblyHelper.cs
@@ -1,30 +1,27 @@
-using System.Reflection;
-using System.Runtime.Loader;
+using System.Runtime.Loader;
+using Fantasy.Generated;
-namespace NB
+namespace Fantasy
{
public static class AssemblyHelper
{
private const string HotfixDll = "Hotfix";
private static AssemblyLoadContext? _assemblyLoadContext = null;
-
- public static System.Reflection.Assembly[] Assemblies
+
+ public static void Initialize()
{
- get
- {
- var assemblies = new System.Reflection.Assembly[2];
- assemblies[0] = LoadEntityAssembly();
- assemblies[1] = LoadHotfixAssembly();
- return assemblies;
- }
+ LoadEntityAssembly();
+ LoadHotfixAssembly();
}
- private static System.Reflection.Assembly LoadEntityAssembly()
+ private static void LoadEntityAssembly()
{
- return typeof(AssemblyHelper).Assembly;
+ // .NET 运行时采用延迟加载机制,如果代码中不使用程序集的类型,程序集不会被加载
+ // 执行一下,触发运行时强制加载从而自动注册到框架中
+ Entity_AssemblyMarker.EnsureLoaded();
}
- private static System.Reflection.Assembly LoadHotfixAssembly()
+ public static System.Reflection.Assembly LoadHotfixAssembly()
{
if (_assemblyLoadContext != null)
{
@@ -33,9 +30,20 @@ namespace NB
}
_assemblyLoadContext = new AssemblyLoadContext(HotfixDll, true);
- var dllBytes = File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, $"{HotfixDll}.dll"));
- var pdbBytes = File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, $"{HotfixDll}.pdb"));
- return _assemblyLoadContext.LoadFromStream(new MemoryStream(dllBytes), new MemoryStream(pdbBytes));
+ var dllBytes = File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, $"{HotfixDll}.dll"));
+ var pdbBytes = File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, $"{HotfixDll}.pdb"));
+ var assembly = _assemblyLoadContext.LoadFromStream(new MemoryStream(dllBytes), new MemoryStream(pdbBytes));
+ // 强制触发 ModuleInitializer 执行
+ // AssemblyLoadContext.LoadFromStream 只加载程序集到内存,不会自动触发 ModuleInitializer
+ // 必须访问程序集中的类型才能触发初始化,这里通过反射调用生成的 AssemblyMarker
+ // 注意:此方法仅用于热重载场景(JIT),Native AOT 不支持动态加载
+ var markerType = assembly.GetType("Fantasy.Generated.Hotfix_AssemblyMarker");
+ if (markerType != null)
+ {
+ var method = markerType.GetMethod("EnsureLoaded");
+ method?.Invoke(null, null);
+ }
+ return assembly;
}
}
}
\ No newline at end of file
diff --git a/Entity/Entity.csproj b/Entity/Entity.csproj
index 5a06389..e4a5a40 100644
--- a/Entity/Entity.csproj
+++ b/Entity/Entity.csproj
@@ -9,31 +9,33 @@
- TRACE;FANTASY_NET
+ TRACE;FANTASY_NET
- TRACE;FANTASY_NET
+ TRACE;FANTASY_NET
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
diff --git a/Entity/Generate/ConfigTable/Entity/BaitConfig.cs b/Entity/Generate/ConfigTable/Entity/BaitConfig.cs
index a38b53c..945d28d 100644
--- a/Entity/Generate/ConfigTable/Entity/BaitConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/BaitConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class BaitConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class BaitConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/BasicConfig.cs b/Entity/Generate/ConfigTable/Entity/BasicConfig.cs
index a9a9cbb..ba6d2e2 100644
--- a/Entity/Generate/ConfigTable/Entity/BasicConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/BasicConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class BasicConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class BasicConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/BobberConfig.cs b/Entity/Generate/ConfigTable/Entity/BobberConfig.cs
index d6ca6db..782f5bb 100644
--- a/Entity/Generate/ConfigTable/Entity/BobberConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/BobberConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class BobberConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class BobberConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/FeederConfig.cs b/Entity/Generate/ConfigTable/Entity/FeederConfig.cs
index efab711..4ffc1f0 100644
--- a/Entity/Generate/ConfigTable/Entity/FeederConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/FeederConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class FeederConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class FeederConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/FishConfig.cs b/Entity/Generate/ConfigTable/Entity/FishConfig.cs
index ed434cf..9a8da1e 100644
--- a/Entity/Generate/ConfigTable/Entity/FishConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/FishConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class FishConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class FishConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/HookConfig.cs b/Entity/Generate/ConfigTable/Entity/HookConfig.cs
index 4fc28ce..747dde9 100644
--- a/Entity/Generate/ConfigTable/Entity/HookConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/HookConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class HookConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class HookConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/InitConfig.cs b/Entity/Generate/ConfigTable/Entity/InitConfig.cs
index 7abba17..1e4806a 100644
--- a/Entity/Generate/ConfigTable/Entity/InitConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/InitConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class InitConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class InitConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/ItemConfig.cs b/Entity/Generate/ConfigTable/Entity/ItemConfig.cs
index 89302f0..f3bbe4d 100644
--- a/Entity/Generate/ConfigTable/Entity/ItemConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/ItemConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class ItemConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class ItemConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/LineConfig.cs b/Entity/Generate/ConfigTable/Entity/LineConfig.cs
index 0ab44c7..8d0dab9 100644
--- a/Entity/Generate/ConfigTable/Entity/LineConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/LineConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class LineConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class LineConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/LureConfig.cs b/Entity/Generate/ConfigTable/Entity/LureConfig.cs
index 0b733e2..9029db9 100644
--- a/Entity/Generate/ConfigTable/Entity/LureConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/LureConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class LureConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class LureConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/ReelConfig.cs b/Entity/Generate/ConfigTable/Entity/ReelConfig.cs
index b824471..36d031a 100644
--- a/Entity/Generate/ConfigTable/Entity/ReelConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/ReelConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class ReelConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class ReelConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/RingConfig.cs b/Entity/Generate/ConfigTable/Entity/RingConfig.cs
deleted file mode 100644
index 42b537f..0000000
--- a/Entity/Generate/ConfigTable/Entity/RingConfig.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using System;
-using ProtoBuf;
-using Fantasy;
-using System.Linq;
-using System.Reflection;
-using System.Collections.Generic;
-using System.Collections.Concurrent;
-using Fantasy.Serialize;
-using Fantasy.ConfigTable;
-
-namespace NBF
-{
- [ProtoContract]
- public sealed partial class RingConfig : ASerialize, IProto, IConfigTable
- {
-
- [ProtoMember(1)]
- public uint Id { get; set; } // Id
- [ProtoMember(2)]
- public string Model { get; set; } // 模型
- [ProtoMember(3)]
- public string Icon { get; set; } // 图标
- [ProtoIgnore]
- public uint Key => Id;
-
- #region Static
-
- private static ConfigContext Context => ConfigTableHelper.Table();
-
- public static RingConfig Get(uint key)
- {
- return Context.Get(key);
- }
-
- public static RingConfig Get(Predicate match)
- {
- return Context.Get(match);
- }
-
- public static RingConfig Fist()
- {
- return Context.Fist();
- }
-
- public static RingConfig Last()
- {
- return Context.Last();
- }
-
- public static RingConfig Fist(Predicate match)
- {
- return Context.Fist(match);
- }
-
- public static RingConfig Last(Predicate match)
- {
- return Context.Last(match);
- }
-
- public static int Count()
- {
- return Context.Count();
- }
-
- public static int Count(Func predicate)
- {
- return Context.Count(predicate);
- }
-
- public static List GetList()
- {
- return Context.GetList();
- }
-
- public static List GetList(Predicate match)
- {
- return Context.GetList(match);
- }
- public static void ParseJson(Newtonsoft.Json.Linq.JArray arr)
- {
- ConfigTableHelper.ParseLine(arr);
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/RodConfig.cs b/Entity/Generate/ConfigTable/Entity/RodConfig.cs
index 4266ee6..ea0445c 100644
--- a/Entity/Generate/ConfigTable/Entity/RodConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/RodConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class RodConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class RodConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/RodRingConfig.cs b/Entity/Generate/ConfigTable/Entity/RodRingConfig.cs
index 5502d6a..fe90c01 100644
--- a/Entity/Generate/ConfigTable/Entity/RodRingConfig.cs
+++ b/Entity/Generate/ConfigTable/Entity/RodRingConfig.cs
@@ -11,7 +11,7 @@ using Fantasy.ConfigTable;
namespace NBF
{
[ProtoContract]
- public sealed partial class RodRingConfig : ASerialize, IProto, IConfigTable
+ public sealed partial class RodRingConfig : ASerialize, IConfigTable
{
[ProtoMember(1)]
diff --git a/Entity/Generate/ConfigTable/Entity/WeightConfig.cs b/Entity/Generate/ConfigTable/Entity/WeightConfig.cs
deleted file mode 100644
index 95d355c..0000000
--- a/Entity/Generate/ConfigTable/Entity/WeightConfig.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-using System;
-using ProtoBuf;
-using Fantasy;
-using System.Linq;
-using System.Reflection;
-using System.Collections.Generic;
-using System.Collections.Concurrent;
-using Fantasy.Serialize;
-using Fantasy.ConfigTable;
-
-namespace NBF
-{
- [ProtoContract]
- public sealed partial class WeightConfig : ASerialize, IProto, IConfigTable
- {
-
- [ProtoMember(1)]
- public uint Id { get; set; } // Id
- [ProtoMember(2)]
- public string Model { get; set; } // 模型
- [ProtoMember(3)]
- public string Icon { get; set; } // 图标
- [ProtoMember(4)]
- public uint Type { get; set; } // 类型
- [ProtoMember(5)]
- public uint Weight { get; set; } // 重量(克)
- [ProtoIgnore]
- public uint Key => Id;
-
- #region Static
-
- private static ConfigContext Context => ConfigTableHelper.Table();
-
- public static WeightConfig Get(uint key)
- {
- return Context.Get(key);
- }
-
- public static WeightConfig Get(Predicate match)
- {
- return Context.Get(match);
- }
-
- public static WeightConfig Fist()
- {
- return Context.Fist();
- }
-
- public static WeightConfig Last()
- {
- return Context.Last();
- }
-
- public static WeightConfig Fist(Predicate match)
- {
- return Context.Fist(match);
- }
-
- public static WeightConfig Last(Predicate match)
- {
- return Context.Last(match);
- }
-
- public static int Count()
- {
- return Context.Count();
- }
-
- public static int Count(Func predicate)
- {
- return Context.Count(predicate);
- }
-
- public static List GetList()
- {
- return Context.GetList();
- }
-
- public static List GetList(Predicate match)
- {
- return Context.GetList(match);
- }
- public static void ParseJson(Newtonsoft.Json.Linq.JArray arr)
- {
- ConfigTableHelper.ParseLine(arr);
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/Entity/Generate/NetworkProtocol/CommonProtoData.cs b/Entity/Generate/NetworkProtocol/CommonProtoData.cs
index c90bbd5..86b2633 100644
--- a/Entity/Generate/NetworkProtocol/CommonProtoData.cs
+++ b/Entity/Generate/NetworkProtocol/CommonProtoData.cs
@@ -1,5 +1,6 @@
using ProtoBuf;
+using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Fantasy;
@@ -16,12 +17,12 @@ using Fantasy.Serialize;
#pragma warning disable CS8618
namespace Fantasy
-{
+{
///
/// 角色基础信息
///
[ProtoContract]
- public partial class RoleBaseInfo : AMessage, IProto
+ public partial class RoleBaseInfo : AMessage
{
public static RoleBaseInfo Create(Scene scene)
{
@@ -53,7 +54,7 @@ namespace Fantasy
public VipInfo VipInfo { get; set; }
}
[ProtoContract]
- public partial class KeyValueInt64 : AMessage, IProto
+ public partial class KeyValueInt64 : AMessage
{
public static KeyValueInt64 Create(Scene scene)
{
@@ -76,7 +77,7 @@ namespace Fantasy
/// 角色信息
///
[ProtoContract]
- public partial class RoleInfo : AMessage, IProto
+ public partial class RoleInfo : AMessage
{
public static RoleInfo Create(Scene scene)
{
@@ -123,7 +124,7 @@ namespace Fantasy
/// 角色信息
///
[ProtoContract]
- public partial class RoleSimpleInfo : AMessage, IProto
+ public partial class RoleSimpleInfo : AMessage
{
public static RoleSimpleInfo Create(Scene scene)
{
@@ -161,7 +162,7 @@ namespace Fantasy
/// VIP信息
///
[ProtoContract]
- public partial class VipInfo : AMessage, IProto
+ public partial class VipInfo : AMessage
{
public static VipInfo Create(Scene scene)
{
@@ -187,7 +188,7 @@ namespace Fantasy
/// 奖励信息
///
[ProtoContract]
- public partial class AwardInfo : AMessage, IProto
+ public partial class AwardInfo : AMessage
{
public static AwardInfo Create(Scene scene)
{
@@ -210,7 +211,7 @@ namespace Fantasy
/// 玩家当前使用钓组信息
///
[ProtoContract]
- public partial class ItemBindInfo : AMessage, IProto
+ public partial class ItemBindInfo : AMessage
{
public static ItemBindInfo Create(Scene scene)
{
@@ -233,7 +234,7 @@ namespace Fantasy
/// 物品信息
///
[ProtoContract]
- public partial class ItemInfo : AMessage, IProto
+ public partial class ItemInfo : AMessage
{
public static ItemInfo Create(Scene scene)
{
@@ -268,7 +269,7 @@ namespace Fantasy
/// fish信息
///
[ProtoContract]
- public partial class FishInfo : AMessage, IProto
+ public partial class FishInfo : AMessage
{
public static FishInfo Create(Scene scene)
{
@@ -297,7 +298,7 @@ namespace Fantasy
public long ExpirationTime { get; set; }
}
[ProtoContract]
- public partial class ActivityInfo : AMessage, IProto
+ public partial class ActivityInfo : AMessage
{
public static ActivityInfo Create(Scene scene)
{
@@ -326,7 +327,7 @@ namespace Fantasy
/// 技能情况
///
[ProtoContract]
- public partial class SkillInfo : AMessage, IProto
+ public partial class SkillInfo : AMessage
{
public static SkillInfo Create(Scene scene)
{
@@ -349,3 +350,4 @@ namespace Fantasy
public int Exp { get; set; }
}
}
+
diff --git a/Entity/Generate/NetworkProtocol/GameMessage.cs b/Entity/Generate/NetworkProtocol/GameMessage.cs
index 26c8f1c..fee0e91 100644
--- a/Entity/Generate/NetworkProtocol/GameMessage.cs
+++ b/Entity/Generate/NetworkProtocol/GameMessage.cs
@@ -1,5 +1,6 @@
using ProtoBuf;
+using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Fantasy;
@@ -16,7 +17,7 @@ using Fantasy.Serialize;
#pragma warning disable CS8618
namespace Fantasy
-{
+{
///
/// /////////// ******** 物品信息 *******/////////////
///
@@ -24,7 +25,7 @@ namespace Fantasy
/// 请求背包列表
///
[ProtoContract]
- public partial class C2Game_GetItemsRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2Game_GetItemsRequest : AMessage, ICustomRouteRequest
{
public static C2Game_GetItemsRequest Create(Scene scene)
{
@@ -46,7 +47,7 @@ namespace Fantasy
/// 请求背包列表响应
///
[ProtoContract]
- public partial class Game2C_GetItemsResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class Game2C_GetItemsResponse : AMessage, ICustomRouteResponse
{
public static Game2C_GetItemsResponse Create(Scene scene)
{
@@ -73,7 +74,7 @@ namespace Fantasy
/// 请求使用物品
///
[ProtoContract]
- public partial class C2Game_UseItemRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2Game_UseItemRequest : AMessage, ICustomRouteRequest
{
public static C2Game_UseItemRequest Create(Scene scene)
{
@@ -95,7 +96,7 @@ namespace Fantasy
/// 请求使用物品响应
///
[ProtoContract]
- public partial class Game2C_UseItemResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class Game2C_UseItemResponse : AMessage, ICustomRouteResponse
{
public static Game2C_UseItemResponse Create(Scene scene)
{
@@ -116,7 +117,7 @@ namespace Fantasy
/// 物品变化
///
[ProtoContract]
- public partial class Game2C_ItemChange : AMessage, ICustomRouteMessage, IProto
+ public partial class Game2C_ItemChange : AMessage, ICustomRouteMessage
{
public static Game2C_ItemChange Create(Scene scene)
{
@@ -148,7 +149,7 @@ namespace Fantasy
/// 请求安装或取下配件
///
[ProtoContract]
- public partial class C2Game_RigChangeRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2Game_RigChangeRequest : AMessage, ICustomRouteRequest
{
public static C2Game_RigChangeRequest Create(Scene scene)
{
@@ -179,7 +180,7 @@ namespace Fantasy
/// 请求安装配件响应
///
[ProtoContract]
- public partial class Game2C_RigChangeResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class Game2C_RigChangeResponse : AMessage, ICustomRouteResponse
{
public static Game2C_RigChangeResponse Create(Scene scene)
{
@@ -206,7 +207,7 @@ namespace Fantasy
/// 请求鱼护列表
///
[ProtoContract]
- public partial class C2Game_GetFishsRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2Game_GetFishsRequest : AMessage, ICustomRouteRequest
{
public static C2Game_GetFishsRequest Create(Scene scene)
{
@@ -228,7 +229,7 @@ namespace Fantasy
/// 请求鱼护列表响应
///
[ProtoContract]
- public partial class Game2C_GetFishsResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class Game2C_GetFishsResponse : AMessage, ICustomRouteResponse
{
public static Game2C_GetFishsResponse Create(Scene scene)
{
@@ -252,7 +253,7 @@ namespace Fantasy
/// 鱼护变化
///
[ProtoContract]
- public partial class Game2C_FishChange : AMessage, ICustomRouteMessage, IProto
+ public partial class Game2C_FishChange : AMessage, ICustomRouteMessage
{
public static Game2C_FishChange Create(Scene scene)
{
@@ -281,7 +282,7 @@ namespace Fantasy
/// 请求出售
///
[ProtoContract]
- public partial class C2Game_SellFishRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2Game_SellFishRequest : AMessage, ICustomRouteRequest
{
public static C2Game_SellFishRequest Create(Scene scene)
{
@@ -306,7 +307,7 @@ namespace Fantasy
/// 请求出售响应
///
[ProtoContract]
- public partial class Game2C_SellFishResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class Game2C_SellFishResponse : AMessage, ICustomRouteResponse
{
public static Game2C_SellFishResponse Create(Scene scene)
{
@@ -333,7 +334,7 @@ namespace Fantasy
/// 请求购买
///
[ProtoContract]
- public partial class C2Game_BuyRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2Game_BuyRequest : AMessage, ICustomRouteRequest
{
public static C2Game_BuyRequest Create(Scene scene)
{
@@ -355,7 +356,7 @@ namespace Fantasy
/// 请求购买响应
///
[ProtoContract]
- public partial class Game2C_BuyResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class Game2C_BuyResponse : AMessage, ICustomRouteResponse
{
public static Game2C_BuyResponse Create(Scene scene)
{
@@ -376,3 +377,4 @@ namespace Fantasy
public uint ErrorCode { get; set; }
}
}
+
diff --git a/Entity/Generate/NetworkProtocol/InnerMessage.cs b/Entity/Generate/NetworkProtocol/InnerMessage.cs
index 34819f3..60806ce 100644
--- a/Entity/Generate/NetworkProtocol/InnerMessage.cs
+++ b/Entity/Generate/NetworkProtocol/InnerMessage.cs
@@ -1,5 +1,6 @@
using ProtoBuf;
+using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Fantasy;
@@ -16,12 +17,12 @@ using Fantasy.Serialize;
#pragma warning disable CS8618
namespace Fantasy
-{
+{
///
/// 通知游戏服角色进入该游戏服
///
[ProtoContract]
- public partial class G2Common_EnterRequest : AMessage, IRouteRequest, IProto
+ public partial class G2Common_EnterRequest : AMessage, IRouteRequest
{
public static G2Common_EnterRequest Create(Scene scene)
{
@@ -47,7 +48,7 @@ namespace Fantasy
public int RouteType { get; set; }
}
[ProtoContract]
- public partial class G2Common_EnterResponse : AMessage, IRouteResponse, IProto
+ public partial class G2Common_EnterResponse : AMessage, IRouteResponse
{
public static G2Common_EnterResponse Create(Scene scene)
{
@@ -71,7 +72,7 @@ namespace Fantasy
public uint ErrorCode { get; set; }
}
[ProtoContract]
- public partial class G2Common_ExitRequest : AMessage, IRouteRequest, IProto
+ public partial class G2Common_ExitRequest : AMessage, IRouteRequest
{
public static G2Common_ExitRequest Create(Scene scene)
{
@@ -94,7 +95,7 @@ namespace Fantasy
public long GateRouteId { get; set; }
}
[ProtoContract]
- public partial class Common2G_ExitResponse : AMessage, IRouteResponse, IProto
+ public partial class Common2G_ExitResponse : AMessage, IRouteResponse
{
public static Common2G_ExitResponse Create(Scene scene)
{
@@ -115,7 +116,7 @@ namespace Fantasy
/// 获取玩家基础信息
///
[ProtoContract]
- public partial class S2G_GetPlayerBasicInfoRequest : AMessage, IRouteRequest, IProto
+ public partial class S2G_GetPlayerBasicInfoRequest : AMessage, IRouteRequest
{
public static S2G_GetPlayerBasicInfoRequest Create(Scene scene)
{
@@ -138,7 +139,7 @@ namespace Fantasy
/// 获取玩家基础信息响应
///
[ProtoContract]
- public partial class G2S_GetPlayerBasicInfoResponse : AMessage, IRouteResponse, IProto
+ public partial class G2S_GetPlayerBasicInfoResponse : AMessage, IRouteResponse
{
public static G2S_GetPlayerBasicInfoResponse Create(Scene scene)
{
@@ -159,7 +160,7 @@ namespace Fantasy
public uint ErrorCode { get; set; }
}
[ProtoContract]
- public partial class S2G_ChatMessage : AMessage, IRouteMessage, IProto
+ public partial class S2G_ChatMessage : AMessage, IRouteMessage
{
public static S2G_ChatMessage Create(Scene scene)
{
@@ -183,7 +184,7 @@ namespace Fantasy
/// 创建聊天频道
///
[ProtoContract]
- public partial class Club2Chat_CreateChannel : AMessage, IRouteMessage, IProto
+ public partial class Club2Chat_CreateChannel : AMessage, IRouteMessage
{
public static Club2Chat_CreateChannel Create(Scene scene)
{
@@ -204,7 +205,7 @@ namespace Fantasy
/// 请求进入房间
///
[ProtoContract]
- public partial class G2Map_EnterMapRequest : AMessage, IRouteRequest, IProto
+ public partial class G2Map_EnterMapRequest : AMessage, IRouteRequest
{
public static G2Map_EnterMapRequest Create(Scene scene)
{
@@ -233,7 +234,7 @@ namespace Fantasy
/// 请求进入房间响应
///
[ProtoContract]
- public partial class Map2G_EnterMapResponse : AMessage, IRouteResponse, IProto
+ public partial class Map2G_EnterMapResponse : AMessage, IRouteResponse
{
public static Map2G_EnterMapResponse Create(Scene scene)
{
@@ -263,7 +264,7 @@ namespace Fantasy
/// 请求离开房间
///
[ProtoContract]
- public partial class G2Map_ExitRoomRequest : AMessage, IRouteRequest, IProto
+ public partial class G2Map_ExitRoomRequest : AMessage, IRouteRequest
{
public static G2Map_ExitRoomRequest Create(Scene scene)
{
@@ -289,7 +290,7 @@ namespace Fantasy
/// 请求离开房间响应
///
[ProtoContract]
- public partial class Map2G_ExiRoomResponse : AMessage, IRouteResponse, IProto
+ public partial class Map2G_ExiRoomResponse : AMessage, IRouteResponse
{
public static Map2G_ExiRoomResponse Create(Scene scene)
{
@@ -307,3 +308,4 @@ namespace Fantasy
public uint ErrorCode { get; set; }
}
}
+
diff --git a/Entity/Generate/NetworkProtocol/MapMessage.cs b/Entity/Generate/NetworkProtocol/MapMessage.cs
index 2a02cc7..f36fb38 100644
--- a/Entity/Generate/NetworkProtocol/MapMessage.cs
+++ b/Entity/Generate/NetworkProtocol/MapMessage.cs
@@ -1,5 +1,6 @@
using ProtoBuf;
+using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Fantasy;
@@ -16,12 +17,12 @@ using Fantasy.Serialize;
#pragma warning disable CS8618
namespace Fantasy
-{
+{
///
/// 请求创建房间
///
[ProtoContract]
- public partial class C2Map_CreateRoomRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2Map_CreateRoomRequest : AMessage, ICustomRouteRequest
{
public static C2Map_CreateRoomRequest Create(Scene scene)
{
@@ -46,7 +47,7 @@ namespace Fantasy
/// 请求创建房间成功
///
[ProtoContract]
- public partial class Map2C_CreateRoomResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class Map2C_CreateRoomResponse : AMessage, ICustomRouteResponse
{
public static Map2C_CreateRoomResponse Create(Scene scene)
{
@@ -73,7 +74,7 @@ namespace Fantasy
/// 请求网关离开房间(离开房间,但是不离开地图)
///
[ProtoContract]
- public partial class C2G_ExitRoomRequest : AMessage, IRequest, IProto
+ public partial class C2G_ExitRoomRequest : AMessage, IRequest
{
public static C2G_ExitRoomRequest Create(Scene scene)
{
@@ -96,7 +97,7 @@ namespace Fantasy
/// 请求网关进入离开响应
///
[ProtoContract]
- public partial class G2C_ExitRoomResponse : AMessage, IResponse, IProto
+ public partial class G2C_ExitRoomResponse : AMessage, IResponse
{
public static G2C_ExitRoomResponse Create(Scene scene)
{
@@ -120,7 +121,7 @@ namespace Fantasy
/// 请求网关进入地图
///
[ProtoContract]
- public partial class C2G_EnterMapRequest : AMessage, IRequest, IProto
+ public partial class C2G_EnterMapRequest : AMessage, IRequest
{
public static C2G_EnterMapRequest Create(Scene scene)
{
@@ -146,7 +147,7 @@ namespace Fantasy
/// 请求网关进入房间响应
///
[ProtoContract]
- public partial class G2C_EnterMapResponse : AMessage, IResponse, IProto
+ public partial class G2C_EnterMapResponse : AMessage, IResponse
{
public static G2C_EnterMapResponse Create(Scene scene)
{
@@ -176,7 +177,7 @@ namespace Fantasy
/// 通知客户端切换地图
///
[ProtoContract]
- public partial class Map2C_ChangeMap : AMessage, ICustomRouteMessage, IProto
+ public partial class Map2C_ChangeMap : AMessage, ICustomRouteMessage
{
public static Map2C_ChangeMap Create(Scene scene)
{
@@ -199,3 +200,4 @@ namespace Fantasy
public int Node { get; set; }
}
}
+
diff --git a/Entity/Generate/NetworkProtocol/MapProtoData.cs b/Entity/Generate/NetworkProtocol/MapProtoData.cs
index 23552c9..2578965 100644
--- a/Entity/Generate/NetworkProtocol/MapProtoData.cs
+++ b/Entity/Generate/NetworkProtocol/MapProtoData.cs
@@ -1,5 +1,6 @@
using ProtoBuf;
+using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Fantasy;
@@ -16,9 +17,9 @@ using Fantasy.Serialize;
#pragma warning disable CS8618
namespace Fantasy
-{
+{
[ProtoContract]
- public partial class Vector3Info : AMessage, IProto
+ public partial class Vector3Info : AMessage
{
public static Vector3Info Create(Scene scene)
{
@@ -41,7 +42,7 @@ namespace Fantasy
public float z { get; set; }
}
[ProtoContract]
- public partial class Vector2Info : AMessage, IProto
+ public partial class Vector2Info : AMessage
{
public static Vector2Info Create(Scene scene)
{
@@ -61,7 +62,7 @@ namespace Fantasy
public float y { get; set; }
}
[ProtoContract]
- public partial class QuaternionInfo : AMessage, IProto
+ public partial class QuaternionInfo : AMessage
{
public static QuaternionInfo Create(Scene scene)
{
@@ -90,7 +91,7 @@ namespace Fantasy
/// 玩家当前使用钓组信息
///
[ProtoContract]
- public partial class GearInfo : AMessage, IProto
+ public partial class GearInfo : AMessage
{
public static GearInfo Create(Scene scene)
{
@@ -119,7 +120,7 @@ namespace Fantasy
public List Propertys = new List();
}
[ProtoContract]
- public partial class UnitStateInfo : AMessage, IProto
+ public partial class UnitStateInfo : AMessage
{
public static UnitStateInfo Create(Scene scene)
{
@@ -139,7 +140,7 @@ namespace Fantasy
public List Propertys = new List();
}
[ProtoContract]
- public partial class MapUnitInfo : AMessage, IProto
+ public partial class MapUnitInfo : AMessage
{
public static MapUnitInfo Create(Scene scene)
{
@@ -174,3 +175,4 @@ namespace Fantasy
public List Propertys = new List();
}
}
+
diff --git a/Entity/Generate/NetworkProtocol/OuterMessage.cs b/Entity/Generate/NetworkProtocol/OuterMessage.cs
index 4af2453..a90f841 100644
--- a/Entity/Generate/NetworkProtocol/OuterMessage.cs
+++ b/Entity/Generate/NetworkProtocol/OuterMessage.cs
@@ -1,5 +1,6 @@
using ProtoBuf;
+using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Fantasy;
@@ -16,9 +17,9 @@ using Fantasy.Serialize;
#pragma warning disable CS8618
namespace Fantasy
-{
+{
[ProtoContract]
- public partial class C2A_LoginRequest : AMessage, IRequest, IProto
+ public partial class C2A_LoginRequest : AMessage, IRequest
{
public static C2A_LoginRequest Create(Scene scene)
{
@@ -47,7 +48,7 @@ namespace Fantasy
public int Region { get; set; }
}
[ProtoContract]
- public partial class A2C_LoginResponse : AMessage, IResponse, IProto
+ public partial class A2C_LoginResponse : AMessage, IResponse
{
public static A2C_LoginResponse Create(Scene scene)
{
@@ -71,7 +72,7 @@ namespace Fantasy
/// 客户端登录到Gate服务器
///
[ProtoContract]
- public partial class C2G_LoginRequest : AMessage, IRequest, IProto
+ public partial class C2G_LoginRequest : AMessage, IRequest
{
public static C2G_LoginRequest Create(Scene scene)
{
@@ -91,7 +92,7 @@ namespace Fantasy
public string ToKen { get; set; }
}
[ProtoContract]
- public partial class G2C_LoginResponse : AMessage, IResponse, IProto
+ public partial class G2C_LoginResponse : AMessage, IResponse
{
public static G2C_LoginResponse Create(Scene scene)
{
@@ -115,7 +116,7 @@ namespace Fantasy
/// 通知客户端重复登录
///
[ProtoContract]
- public partial class G2C_RepeatLogin : AMessage, IMessage, IProto
+ public partial class G2C_RepeatLogin : AMessage, IMessage
{
public static G2C_RepeatLogin Create(Scene scene)
{
@@ -130,7 +131,7 @@ namespace Fantasy
public uint OpCode() { return OuterOpcode.G2C_RepeatLogin; }
}
[ProtoContract]
- public partial class C2Game_GetRoleInfoRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2Game_GetRoleInfoRequest : AMessage, ICustomRouteRequest
{
public static C2Game_GetRoleInfoRequest Create(Scene scene)
{
@@ -149,7 +150,7 @@ namespace Fantasy
public int RouteType => Fantasy.RouteType.GameRoute;
}
[ProtoContract]
- public partial class Game2C_GetRoleInfoResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class Game2C_GetRoleInfoResponse : AMessage, ICustomRouteResponse
{
public static Game2C_GetRoleInfoResponse Create(Scene scene)
{
@@ -173,3 +174,4 @@ namespace Fantasy
public uint ErrorCode { get; set; }
}
}
+
diff --git a/Entity/Generate/NetworkProtocol/RoomMessage.cs b/Entity/Generate/NetworkProtocol/RoomMessage.cs
index 8bb37e2..41c37e0 100644
--- a/Entity/Generate/NetworkProtocol/RoomMessage.cs
+++ b/Entity/Generate/NetworkProtocol/RoomMessage.cs
@@ -1,5 +1,6 @@
using ProtoBuf;
+using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Fantasy;
@@ -16,12 +17,12 @@ using Fantasy.Serialize;
#pragma warning disable CS8618
namespace Fantasy
-{
+{
///
/// 用户进入地图
///
[ProtoContract]
- public partial class Map2C_RoleEnterRoomNotify : AMessage, ICustomRouteMessage, IProto
+ public partial class Map2C_RoleEnterRoomNotify : AMessage, ICustomRouteMessage
{
public static Map2C_RoleEnterRoomNotify Create(Scene scene)
{
@@ -44,7 +45,7 @@ namespace Fantasy
/// 用户离开地图
///
[ProtoContract]
- public partial class Map2C_RoleExitRoomNotify : AMessage, ICustomRouteMessage, IProto
+ public partial class Map2C_RoleExitRoomNotify : AMessage, ICustomRouteMessage
{
public static Map2C_RoleExitRoomNotify Create(Scene scene)
{
@@ -64,7 +65,7 @@ namespace Fantasy
public long Id { get; set; }
}
[ProtoContract]
- public partial class C2Map_RolePropertyChange : AMessage, ICustomRouteMessage, IProto
+ public partial class C2Map_RolePropertyChange : AMessage, ICustomRouteMessage
{
public static C2Map_RolePropertyChange Create(Scene scene)
{
@@ -87,7 +88,7 @@ namespace Fantasy
/// 玩家状态变化同步
///
[ProtoContract]
- public partial class Map2C_RoleStateNotify : AMessage, ICustomRouteMessage, IProto
+ public partial class Map2C_RoleStateNotify : AMessage, ICustomRouteMessage
{
public static Map2C_RoleStateNotify Create(Scene scene)
{
@@ -113,7 +114,7 @@ namespace Fantasy
/// 玩家钓组变化
///
[ProtoContract]
- public partial class Map2C_RoleGearChangeNotify : AMessage, ICustomRouteMessage, IProto
+ public partial class Map2C_RoleGearChangeNotify : AMessage, ICustomRouteMessage
{
public static Map2C_RoleGearChangeNotify Create(Scene scene)
{
@@ -136,7 +137,7 @@ namespace Fantasy
public List Gears = new List();
}
[ProtoContract]
- public partial class Map2C_RolePropertyChangeNotify : AMessage, ICustomRouteMessage, IProto
+ public partial class Map2C_RolePropertyChangeNotify : AMessage, ICustomRouteMessage
{
public static Map2C_RolePropertyChangeNotify Create(Scene scene)
{
@@ -159,7 +160,7 @@ namespace Fantasy
public List Propertys = new List();
}
[ProtoContract]
- public partial class C2Map_Move : AMessage, ICustomRouteMessage, IProto
+ public partial class C2Map_Move : AMessage, ICustomRouteMessage
{
public static C2Map_Move Create(Scene scene)
{
@@ -194,7 +195,7 @@ namespace Fantasy
public long Timestamp { get; set; }
}
[ProtoContract]
- public partial class C2Map_Look : AMessage, ICustomRouteMessage, IProto
+ public partial class C2Map_Look : AMessage, ICustomRouteMessage
{
public static C2Map_Look Create(Scene scene)
{
@@ -220,7 +221,7 @@ namespace Fantasy
/// 玩家移动推送
///
[ProtoContract]
- public partial class Map2C_MoveNotify : AMessage, ICustomRouteMessage, IProto
+ public partial class Map2C_MoveNotify : AMessage, ICustomRouteMessage
{
public static Map2C_MoveNotify Create(Scene scene)
{
@@ -261,7 +262,7 @@ namespace Fantasy
/// 玩家旋转推送
///
[ProtoContract]
- public partial class Map2C_LookeNotify : AMessage, ICustomRouteMessage, IProto
+ public partial class Map2C_LookeNotify : AMessage, ICustomRouteMessage
{
public static Map2C_LookeNotify Create(Scene scene)
{
@@ -287,3 +288,4 @@ namespace Fantasy
public long Timestamp { get; set; }
}
}
+
diff --git a/Entity/Generate/NetworkProtocol/SocialMessage.cs b/Entity/Generate/NetworkProtocol/SocialMessage.cs
index 5a802a5..cf1ab9b 100644
--- a/Entity/Generate/NetworkProtocol/SocialMessage.cs
+++ b/Entity/Generate/NetworkProtocol/SocialMessage.cs
@@ -1,5 +1,6 @@
using ProtoBuf;
+using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Fantasy;
@@ -16,7 +17,7 @@ using Fantasy.Serialize;
#pragma warning disable CS8618
namespace Fantasy
-{
+{
///
/// /////////// ******** 私聊/邮件 *******/////////////
///
@@ -24,7 +25,7 @@ namespace Fantasy
/// 会话信息
///
[ProtoContract]
- public partial class ConversationInfo : AMessage, IProto
+ public partial class ConversationInfo : AMessage
{
public static ConversationInfo Create(Scene scene)
{
@@ -44,7 +45,7 @@ namespace Fantasy
public List List = new List();
}
[ProtoContract]
- public partial class MailInfo : AMessage, IProto
+ public partial class MailInfo : AMessage
{
public static MailInfo Create(Scene scene)
{
@@ -82,7 +83,7 @@ namespace Fantasy
/// 请求会话列表
///
[ProtoContract]
- public partial class C2S_GetConversationsRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_GetConversationsRequest : AMessage, ICustomRouteRequest
{
public static C2S_GetConversationsRequest Create(Scene scene)
{
@@ -104,7 +105,7 @@ namespace Fantasy
/// 请求会话列表响应
///
[ProtoContract]
- public partial class S2C_GetConversationsResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_GetConversationsResponse : AMessage, ICustomRouteResponse
{
public static S2C_GetConversationsResponse Create(Scene scene)
{
@@ -128,7 +129,7 @@ namespace Fantasy
/// 发送邮件消息
///
[ProtoContract]
- public partial class C2S_SendMailRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_SendMailRequest : AMessage, ICustomRouteRequest
{
public static C2S_SendMailRequest Create(Scene scene)
{
@@ -159,7 +160,7 @@ namespace Fantasy
/// 发送邮件消息响应
///
[ProtoContract]
- public partial class S2C_SendMailResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_SendMailResponse : AMessage, ICustomRouteResponse
{
public static S2C_SendMailResponse Create(Scene scene)
{
@@ -180,7 +181,7 @@ namespace Fantasy
/// 发送删除会话消息
///
[ProtoContract]
- public partial class C2S_DeleteMailRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_DeleteMailRequest : AMessage, ICustomRouteRequest
{
public static C2S_DeleteMailRequest Create(Scene scene)
{
@@ -205,7 +206,7 @@ namespace Fantasy
/// 发送删除会话消息响应
///
[ProtoContract]
- public partial class S2C_DeleteMailResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_DeleteMailResponse : AMessage, ICustomRouteResponse
{
public static S2C_DeleteMailResponse Create(Scene scene)
{
@@ -229,7 +230,7 @@ namespace Fantasy
/// 新邮件推送
///
[ProtoContract]
- public partial class S2C_HaveMail : AMessage, ICustomRouteMessage, IProto
+ public partial class S2C_HaveMail : AMessage, ICustomRouteMessage
{
public static S2C_HaveMail Create(Scene scene)
{
@@ -252,7 +253,7 @@ namespace Fantasy
public string Key { get; set; }
}
[ProtoContract]
- public partial class S2C_MailState : AMessage, ICustomRouteMessage, IProto
+ public partial class S2C_MailState : AMessage, ICustomRouteMessage
{
public static S2C_MailState Create(Scene scene)
{
@@ -278,7 +279,7 @@ namespace Fantasy
/// /////////// ******** 频道聊天 *******/////////////
///
[ProtoContract]
- public partial class ChatUserInfo : AMessage, IProto
+ public partial class ChatUserInfo : AMessage
{
public static ChatUserInfo Create(Scene scene)
{
@@ -298,7 +299,7 @@ namespace Fantasy
public long Name { get; set; }
}
[ProtoContract]
- public partial class ChatMessageInfo : AMessage, IProto
+ public partial class ChatMessageInfo : AMessage
{
public static ChatMessageInfo Create(Scene scene)
{
@@ -330,7 +331,7 @@ namespace Fantasy
/// 创建频道
///
[ProtoContract]
- public partial class C2S_CreateChannelRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_CreateChannelRequest : AMessage, ICustomRouteRequest
{
public static C2S_CreateChannelRequest Create(Scene scene)
{
@@ -355,7 +356,7 @@ namespace Fantasy
/// 创建频道响应
///
[ProtoContract]
- public partial class S2C_CreateChannelResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_CreateChannelResponse : AMessage, ICustomRouteResponse
{
public static S2C_CreateChannelResponse Create(Scene scene)
{
@@ -379,7 +380,7 @@ namespace Fantasy
/// 请求进入频道
///
[ProtoContract]
- public partial class C2S_JoinChannelRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_JoinChannelRequest : AMessage, ICustomRouteRequest
{
public static C2S_JoinChannelRequest Create(Scene scene)
{
@@ -404,7 +405,7 @@ namespace Fantasy
/// 进入频道响应
///
[ProtoContract]
- public partial class S2C_JoinChannelResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_JoinChannelResponse : AMessage, ICustomRouteResponse
{
public static S2C_JoinChannelResponse Create(Scene scene)
{
@@ -425,7 +426,7 @@ namespace Fantasy
/// 发送消息
///
[ProtoContract]
- public partial class C2S_SendMessageRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_SendMessageRequest : AMessage, ICustomRouteRequest
{
public static C2S_SendMessageRequest Create(Scene scene)
{
@@ -453,7 +454,7 @@ namespace Fantasy
/// 发送消息响应
///
[ProtoContract]
- public partial class S2C_SendMessageResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_SendMessageResponse : AMessage, ICustomRouteResponse
{
public static S2C_SendMessageResponse Create(Scene scene)
{
@@ -474,7 +475,7 @@ namespace Fantasy
/// 推送消息
///
[ProtoContract]
- public partial class S2C_Message : AMessage, ICustomRouteMessage, IProto
+ public partial class S2C_Message : AMessage, ICustomRouteMessage
{
public static S2C_Message Create(Scene scene)
{
@@ -497,7 +498,7 @@ namespace Fantasy
/// /////////// ******** 工会 *******/////////////
///
[ProtoContract]
- public partial class ClubInfo : AMessage, IProto
+ public partial class ClubInfo : AMessage
{
public static ClubInfo Create(Scene scene)
{
@@ -529,7 +530,7 @@ namespace Fantasy
/// 请求创建工会
///
[ProtoContract]
- public partial class C2S_CreateClubRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_CreateClubRequest : AMessage, ICustomRouteRequest
{
public static C2S_CreateClubRequest Create(Scene scene)
{
@@ -554,7 +555,7 @@ namespace Fantasy
/// 创建工会响应
///
[ProtoContract]
- public partial class S2C_CreateClubResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_CreateClubResponse : AMessage, ICustomRouteResponse
{
public static S2C_CreateClubResponse Create(Scene scene)
{
@@ -578,7 +579,7 @@ namespace Fantasy
/// 请求工会信息
///
[ProtoContract]
- public partial class C2S_GetClubInfoRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_GetClubInfoRequest : AMessage, ICustomRouteRequest
{
public static C2S_GetClubInfoRequest Create(Scene scene)
{
@@ -603,7 +604,7 @@ namespace Fantasy
/// 响应工会信息
///
[ProtoContract]
- public partial class S2C_GetClubInfoResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_GetClubInfoResponse : AMessage, ICustomRouteResponse
{
public static S2C_GetClubInfoResponse Create(Scene scene)
{
@@ -627,7 +628,7 @@ namespace Fantasy
/// 请求工会成员列表
///
[ProtoContract]
- public partial class C2S_GetMemberListRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_GetMemberListRequest : AMessage, ICustomRouteRequest
{
public static C2S_GetMemberListRequest Create(Scene scene)
{
@@ -652,7 +653,7 @@ namespace Fantasy
/// 响应工会成员列表
///
[ProtoContract]
- public partial class S2C_GetMemberListResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_GetMemberListResponse : AMessage, ICustomRouteResponse
{
public static S2C_GetMemberListResponse Create(Scene scene)
{
@@ -676,7 +677,7 @@ namespace Fantasy
/// 获取工会列表请求
///
[ProtoContract]
- public partial class C2S_GetClubListRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_GetClubListRequest : AMessage, ICustomRouteRequest
{
public static C2S_GetClubListRequest Create(Scene scene)
{
@@ -698,7 +699,7 @@ namespace Fantasy
/// 获取工会列表响应
///
[ProtoContract]
- public partial class S2C_GetClubListResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_GetClubListResponse : AMessage, ICustomRouteResponse
{
public static S2C_GetClubListResponse Create(Scene scene)
{
@@ -722,7 +723,7 @@ namespace Fantasy
/// 请求加入工会
///
[ProtoContract]
- public partial class C2S_JoinClubRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_JoinClubRequest : AMessage, ICustomRouteRequest
{
public static C2S_JoinClubRequest Create(Scene scene)
{
@@ -747,7 +748,7 @@ namespace Fantasy
/// 响应加入工会
///
[ProtoContract]
- public partial class S2C_JoinClubResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_JoinClubResponse : AMessage, ICustomRouteResponse
{
public static S2C_JoinClubResponse Create(Scene scene)
{
@@ -771,7 +772,7 @@ namespace Fantasy
/// 请求退出工会
///
[ProtoContract]
- public partial class C2S_LeaveClubRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_LeaveClubRequest : AMessage, ICustomRouteRequest
{
public static C2S_LeaveClubRequest Create(Scene scene)
{
@@ -796,7 +797,7 @@ namespace Fantasy
/// 响应退出工会
///
[ProtoContract]
- public partial class S2C_LeaveClubResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_LeaveClubResponse : AMessage, ICustomRouteResponse
{
public static S2C_LeaveClubResponse Create(Scene scene)
{
@@ -820,7 +821,7 @@ namespace Fantasy
/// 请求解散工会
///
[ProtoContract]
- public partial class C2S_DissolveClubRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_DissolveClubRequest : AMessage, ICustomRouteRequest
{
public static C2S_DissolveClubRequest Create(Scene scene)
{
@@ -845,7 +846,7 @@ namespace Fantasy
/// 响应解散工会
///
[ProtoContract]
- public partial class S2C_DissolveClubResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_DissolveClubResponse : AMessage, ICustomRouteResponse
{
public static S2C_DissolveClubResponse Create(Scene scene)
{
@@ -869,7 +870,7 @@ namespace Fantasy
/// 请求操作申请
///
[ProtoContract]
- public partial class C2S_DisposeJoinRequest : AMessage, ICustomRouteRequest, IProto
+ public partial class C2S_DisposeJoinRequest : AMessage, ICustomRouteRequest
{
public static C2S_DisposeJoinRequest Create(Scene scene)
{
@@ -900,7 +901,7 @@ namespace Fantasy
/// 响应操作申请
///
[ProtoContract]
- public partial class S2C_DisposeJoinResponse : AMessage, ICustomRouteResponse, IProto
+ public partial class S2C_DisposeJoinResponse : AMessage, ICustomRouteResponse
{
public static S2C_DisposeJoinResponse Create(Scene scene)
{
@@ -930,7 +931,7 @@ namespace Fantasy
/// 推送消息
///
[ProtoContract]
- public partial class S2C_ClubChange : AMessage, ICustomRouteMessage, IProto
+ public partial class S2C_ClubChange : AMessage, ICustomRouteMessage
{
public static S2C_ClubChange Create(Scene scene)
{
@@ -953,3 +954,4 @@ namespace Fantasy
public int ChangeType { get; set; }
}
}
+
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Fantasy-Net.targets b/Fantasy/Fantasy.Net/Fantasy.Net/Fantasy-Net.targets
index 5426ed6..2694462 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Fantasy-Net.targets
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Fantasy-Net.targets
@@ -1,34 +1,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ $(DefineConstants);FANTASY_NET
+
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Fantasy.Net.csproj b/Fantasy/Fantasy.Net/Fantasy.Net/Fantasy.Net.csproj
index be19e19..c08e328 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Fantasy.Net.csproj
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Fantasy.Net.csproj
@@ -30,6 +30,9 @@
true
true
bin\Debug\net8.0\Fantasy.Net.xml
+
+ true
+ $(BaseIntermediateOutputPath)\GeneratedFiles
@@ -57,4 +60,21 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyInfo.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyInfo.cs
deleted file mode 100644
index 3957539..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyInfo.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using Fantasy.DataStructure.Collection;
-
-// ReSharper disable CollectionNeverQueried.Global
-#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
-
-namespace Fantasy.Assembly
-{
- ///
- /// AssemblyInfo提供有关程序集和类型的信息
- ///
- public sealed class AssemblyInfo
- {
- ///
- /// 唯一标识
- ///
- public readonly long AssemblyIdentity;
- ///
- /// 获取或设置与此程序集相关联的 实例。
- ///
- public System.Reflection.Assembly Assembly { get; private set; }
- ///
- /// 程序集类型集合,获取一个列表,包含从程序集加载的所有类型。
- ///
- public readonly List AssemblyTypeList = new List();
- ///
- /// 程序集类型分组集合,获取一个分组列表,将接口类型映射到实现这些接口的类型。
- ///
- public readonly OneToManyList AssemblyTypeGroupList = new OneToManyList();
-
- ///
- /// 初始化 类的新实例。
- ///
- ///
- public AssemblyInfo(long assemblyIdentity)
- {
- AssemblyIdentity = assemblyIdentity;
- }
-
- ///
- /// 从指定的程序集加载类型信息并进行分类。
- ///
- /// 要加载信息的程序集。
- public void Load(System.Reflection.Assembly assembly)
- {
- Assembly = assembly;
- var assemblyTypes = assembly.GetTypes().ToList();
-
- foreach (var type in assemblyTypes)
- {
- if (type.IsAbstract || type.IsInterface)
- {
- continue;
- }
-
- var interfaces = type.GetInterfaces();
-
- foreach (var interfaceType in interfaces)
- {
- AssemblyTypeGroupList.Add(interfaceType, type);
- }
- }
-
- AssemblyTypeList.AddRange(assemblyTypes);
- }
-
- ///
- /// 重新加载程序集的类型信息。
- ///
- ///
- public void ReLoad(System.Reflection.Assembly assembly)
- {
- Unload();
- Load(assembly);
- }
-
- ///
- /// 卸载程序集的类型信息。
- ///
- public void Unload()
- {
- AssemblyTypeList.Clear();
- AssemblyTypeGroupList.Clear();
- }
- }
-}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyLifecycle.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyLifecycle.cs
new file mode 100644
index 0000000..6bd0ee3
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyLifecycle.cs
@@ -0,0 +1,91 @@
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using Fantasy.Async;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 程序集生命周期管理类
+ /// 管理所有注册的程序集生命周期回调,在程序集加载、卸载时触发相应的回调方法
+ ///
+ public static class AssemblyLifecycle
+ {
+#if FANTASY_WEBGL
+ ///
+ /// 程序集生命周期回调集合(WebGL 单线程版本)
+ ///
+ private static readonly Dictionary AssemblyLifecycles = new Dictionary();
+#else
+ ///
+ /// 程序集生命周期回调集合(线程安全版本)
+ /// 使用 ConcurrentDictionary 当作 Set 使用,Value 无实际意义
+ ///
+ private static readonly ConcurrentDictionary AssemblyLifecycles = new ConcurrentDictionary();
+#endif
+ ///
+ /// 触发程序集加载事件
+ /// 遍历所有已注册的生命周期回调,调用其 OnLoad 方法
+ ///
+ /// 程序集清单对象
+ /// 异步任务
+ internal static async FTask OnLoad(AssemblyManifest assemblyManifest)
+ {
+ foreach (var (assemblyLifecycle, _) in AssemblyLifecycles)
+ {
+ await assemblyLifecycle.OnLoad(assemblyManifest);
+ }
+ }
+
+ ///
+ /// 触发程序集卸载事件
+ /// 遍历所有已注册的生命周期回调,调用其 OnUnload 方法,并清理程序集清单
+ ///
+ /// 程序集清单对象
+ /// 异步任务
+ internal static async FTask OnUnLoad(AssemblyManifest assemblyManifest)
+ {
+ foreach (var (assemblyLifecycle, _) in AssemblyLifecycles)
+ {
+ await assemblyLifecycle.OnUnload(assemblyManifest);
+ }
+ assemblyManifest.Clear();
+ }
+
+ ///
+ /// 添加程序集生命周期回调
+ /// 添加后会立即对所有已加载的程序集触发 Load 回调
+ ///
+ /// 实现 IAssemblyLifecycle 接口的生命周期回调对象
+ internal static async FTask Add(IAssemblyLifecycle assemblyLifecycle)
+ {
+#if FANTASY_WEBGL
+ AssemblyLifecycles.Add(assemblyLifecycle, 0);
+#else
+ AssemblyLifecycles.TryAdd(assemblyLifecycle, 0);
+#endif
+ foreach (var (_, assemblyManifest) in AssemblyManifest.Manifests)
+ {
+ await assemblyLifecycle.OnLoad(assemblyManifest);
+ }
+ }
+
+ ///
+ /// 移除程序集生命周期回调
+ /// 移除后该回调将不再接收程序集的加载、卸载、重载事件
+ ///
+ /// 要移除的生命周期回调对象
+ internal static void Remove(IAssemblyLifecycle assemblyLifecycle)
+ {
+ AssemblyLifecycles.Remove(assemblyLifecycle, out _);
+ }
+
+ ///
+ /// 释放所有程序集生命周期回调
+ /// 清空所有已注册的生命周期回调集合
+ ///
+ public static void Dispose()
+ {
+ AssemblyLifecycles.Clear();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyManifest.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyManifest.cs
new file mode 100644
index 0000000..ef47124
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblyManifest.cs
@@ -0,0 +1,256 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using Fantasy.Async;
+using Fantasy.DataStructure.Collection;
+using Fantasy.Entitas;
+// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
+#pragma warning disable CS8602 // Dereference of a possibly null reference.
+#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
+#pragma warning disable CS8601 // Possible null reference assignment.
+#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.
+#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
+#pragma warning disable CS8603 // Possible null reference return.
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 程序集清单类
+ /// 封装程序集的元数据和各种系统注册器,用于统一管理程序集的生命周期和系统注册
+ ///
+ public sealed class AssemblyManifest
+ {
+ ///
+ /// 程序集唯一标识符
+ /// 通过程序集名称的哈希值生成
+ ///
+ public long AssemblyManifestId { get; private set; }
+
+ ///
+ /// 程序集实例
+ ///
+ public System.Reflection.Assembly Assembly { get; private set; }
+
+ ///
+ /// ProtoBuf 序列化类型注册器
+ ///
+ internal INetworkProtocolRegistrar NetworkProtocolRegistrar { get; set; }
+
+ ///
+ /// 事件系统注册器
+ ///
+ internal IEventSystemRegistrar EventSystemRegistrar { get; set; }
+
+ ///
+ /// 实体系统注册器
+ ///
+ internal IEntitySystemRegistrar EntitySystemRegistrar { get; set; }
+
+ ///
+ /// 消息分发器注册器
+ ///
+ internal IMessageHandlerResolver MessageHandlerResolver { get; set; }
+
+ ///
+ /// 实体类型集合注册器
+ ///
+ internal IEntityTypeCollectionRegistrar EntityTypeCollectionRegistrar { get; set; }
+
+ ///
+ /// 网络协议 OpCode 解析器接口
+ ///
+ internal INetworkProtocolOpCodeResolver NetworkProtocolOpCodeResolver { get; set; }
+
+
+ ///
+ /// 网络协议 Response 解析器接口
+ ///
+ internal INetworkProtocolResponseTypeResolver NetworkProtocolResponseTypeResolver { get; set; }
+
+#if FANTASY_NET
+ ///
+ /// 分表注册器
+ ///
+ internal ISeparateTableRegistrar SeparateTableRegistrar { get; set; }
+#endif
+#if FANTASY_WEBGL
+ ///
+ /// 程序集清单集合(WebGL 单线程版本)
+ /// Key: 程序集唯一标识, Value: 程序集清单对象
+ ///
+ private static readonly Dictionary Manifests = new Dictionary();
+#else
+ ///
+ /// 程序集清单集合(线程安全版本)
+ /// Key: 程序集唯一标识, Value: 程序集清单对象
+ ///
+ internal static readonly ConcurrentDictionary Manifests = new ConcurrentDictionary();
+#endif
+ ///
+ /// 清理程序集清单内部资源
+ /// 释放所有注册器并清空引用
+ ///
+ internal void Clear()
+ {
+ EventSystemRegistrar?.Dispose();
+
+ Assembly = null;
+ NetworkProtocolRegistrar = null;
+ EventSystemRegistrar = null;
+ EntitySystemRegistrar = null;
+ MessageHandlerResolver = null;
+ EntityTypeCollectionRegistrar = null;
+#if FANTASY_NET
+ SeparateTableRegistrar = null;
+#endif
+ }
+
+ #region static
+
+#if FANTASY_NET
+ ///
+ /// 注册程序集清单
+ /// 此方法由 Source Generator 生成的 ModuleInitializer 自动调用
+ /// 直接创建并缓存完整的 AssemblyManifest
+ ///
+ /// 程序集唯一标识(通过程序集名称哈希生成)
+ /// 程序集实例
+ /// 网络协议注册器
+ /// 事件系统注册器
+ /// 实体系统注册器
+ /// 消息分发器注册器
+ /// 实体类型集合注册器
+ /// 分表注册器
+ /// 网络协议 OpCode 解析器接口
+ /// 网络协议 Response 解析器接口
+ public static void Register(
+ long assemblyManifestId,
+ System.Reflection.Assembly assembly,
+ INetworkProtocolRegistrar networkProtocolRegistrar,
+ IEventSystemRegistrar eventSystemRegistrar,
+ IEntitySystemRegistrar entitySystemRegistrar,
+ IMessageHandlerResolver messageHandlerResolver,
+ IEntityTypeCollectionRegistrar entityTypeCollectionRegistrar,
+ ISeparateTableRegistrar separateTableRegistrar,
+ INetworkProtocolOpCodeResolver networkProtocolOpCodeResolver,
+ INetworkProtocolResponseTypeResolver networkProtocolResponseTypeResolver)
+ {
+ var manifest = new AssemblyManifest
+ {
+ Assembly = assembly,
+ AssemblyManifestId = assemblyManifestId,
+ NetworkProtocolRegistrar = networkProtocolRegistrar,
+ EventSystemRegistrar = eventSystemRegistrar,
+ EntitySystemRegistrar = entitySystemRegistrar,
+ MessageHandlerResolver = messageHandlerResolver,
+ EntityTypeCollectionRegistrar = entityTypeCollectionRegistrar,
+ SeparateTableRegistrar = separateTableRegistrar,
+ NetworkProtocolOpCodeResolver = networkProtocolOpCodeResolver,
+ NetworkProtocolResponseTypeResolver = networkProtocolResponseTypeResolver
+ };
+
+ Manifests.TryAdd(assemblyManifestId, manifest);
+ AssemblyLifecycle.OnLoad(manifest).Coroutine();
+ }
+#endif
+#if FANTASY_UNITY
+ ///
+ /// 注册程序集清单
+ /// 此方法由 Source Generator 生成的 ModuleInitializer 自动调用
+ /// 直接创建并缓存完整的 AssemblyManifest
+ ///
+ /// 程序集唯一标识(通过程序集名称哈希生成)
+ /// 程序集实例
+ /// 网络协议注册器
+ /// 事件系统注册器
+ /// 实体系统注册器
+ /// 消息分发器注册器
+ /// 实体类型集合注册器
+ /// 网络协议 OpCode 解析器接口
+ /// 网络协议 Response 解析器接口
+ public static void Register(
+ long assemblyManifestId,
+ System.Reflection.Assembly assembly,
+ INetworkProtocolRegistrar networkProtocolRegistrar,
+ IEventSystemRegistrar eventSystemRegistrar,
+ IEntitySystemRegistrar entitySystemRegistrar,
+ IMessageHandlerResolver messageHandlerResolver,
+ IEntityTypeCollectionRegistrar entityTypeCollectionRegistrar,
+ INetworkProtocolOpCodeResolver networkProtocolOpCodeResolver,
+ INetworkProtocolResponseTypeResolver networkProtocolResponseTypeResolver)
+ {
+ var manifest = new AssemblyManifest
+ {
+ Assembly = assembly,
+ AssemblyManifestId = assemblyManifestId,
+ NetworkProtocolRegistrar = networkProtocolRegistrar,
+ EventSystemRegistrar = eventSystemRegistrar,
+ EntitySystemRegistrar = entitySystemRegistrar,
+ MessageHandlerResolver = messageHandlerResolver,
+ EntityTypeCollectionRegistrar = entityTypeCollectionRegistrar,
+ NetworkProtocolOpCodeResolver = networkProtocolOpCodeResolver,
+ NetworkProtocolResponseTypeResolver = networkProtocolResponseTypeResolver
+ };
+#if FANTASY_WEBGL
+ Manifests[assemblyManifestId] = manifest;
+#else
+ Manifests.TryAdd(assemblyManifestId, manifest);
+#endif
+ AssemblyLifecycle.OnLoad(manifest).Coroutine();
+ }
+#endif
+ ///
+ /// 取消注册指定程序集的清单
+ ///
+ /// 程序集唯一标识
+ public static void Unregister(long assemblyManifestId)
+ {
+#if FANTASY_WEBGL
+ if (Manifests.TryGetValue(assemblyManifestId, out var manifest))
+ {
+ AssemblyLifecycle.OnUnLoad(manifest).Coroutine();
+ Manifests.Remove(assemblyManifestId);
+ }
+#else
+ if (Manifests.TryRemove(assemblyManifestId, out var manifest))
+ {
+ AssemblyLifecycle.OnUnLoad(manifest).Coroutine();
+ }
+#endif
+ }
+
+ ///
+ /// 获取当前框架注册的所有程序集清单
+ /// 通过迭代器模式返回所有已注册的程序集清单对象
+ ///
+ public static IEnumerable GetAssemblyManifest
+ {
+ get
+ {
+ foreach (var (_, assemblyManifest) in Manifests)
+ {
+ yield return assemblyManifest;
+ }
+ }
+ }
+
+ ///
+ /// 释放所有程序集清单资源
+ /// 卸载所有已注册的程序集,触发卸载事件,清理所有注册器和生命周期回调
+ ///
+ /// 异步任务
+ public static async FTask Dispose()
+ {
+ foreach (var (_, assemblyManifest) in Manifests)
+ {
+ await AssemblyLifecycle.OnUnLoad(assemblyManifest);
+ assemblyManifest.Clear();
+ }
+
+ Manifests.Clear();
+ AssemblyLifecycle.Dispose();
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblySystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblySystem.cs
deleted file mode 100644
index deb9da6..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/AssemblySystem.cs
+++ /dev/null
@@ -1,285 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Security.Cryptography;
-using System.Text;
-using Fantasy.Async;
-using Fantasy.Helper;
-#pragma warning disable CS8604 // Possible null reference argument.
-#pragma warning disable CS8602 // Dereference of a possibly null reference.
-#pragma warning disable CS8603
-#pragma warning disable CS8618
-namespace Fantasy.Assembly
-{
- ///
- /// 管理程序集加载和卸载的帮助类。
- ///
- public static class AssemblySystem
- {
-#if FANTASY_WEBGL
- private static readonly List AssemblySystems = new List();
- private static readonly Dictionary AssemblyList = new Dictionary();
-#else
- private static readonly ConcurrentQueue AssemblySystems = new ConcurrentQueue();
- private static readonly ConcurrentDictionary AssemblyList = new ConcurrentDictionary();
-#endif
- ///
- /// 初始化 AssemblySystem。(仅限内部)
- ///
- ///
- internal static async FTask InnerInitialize(params System.Reflection.Assembly[] assemblies)
- {
- await LoadAssembly(typeof(AssemblySystem).Assembly);
- foreach (var assembly in assemblies)
- {
- await LoadAssembly(assembly);
- }
- }
-
- ///
- /// 加载指定的程序集,并触发相应的事件。
- ///
- /// 要加载的程序集。
- /// 如果当前Domain中已经存在同名的Assembly,使用Domain中的程序集。
- public static async FTask LoadAssembly(System.Reflection.Assembly assembly, bool isCurrentDomain = true)
- {
- if (isCurrentDomain)
- {
- var currentDomainAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
- var currentAssembly = currentDomainAssemblies.FirstOrDefault(d => d.GetName().Name == assembly.GetName().Name);
- if (currentAssembly != null)
- {
- assembly = currentAssembly;
- }
- }
-
- var assemblyIdentity = AssemblyIdentity(assembly);
-
- if (AssemblyList.TryGetValue(assemblyIdentity, out var assemblyInfo))
- {
- assemblyInfo.ReLoad(assembly);
- foreach (var assemblySystem in AssemblySystems)
- {
- await assemblySystem.ReLoad(assemblyIdentity);
- }
- }
- else
- {
- assemblyInfo = new AssemblyInfo(assemblyIdentity);
- assemblyInfo.Load(assembly);
- AssemblyList.TryAdd(assemblyIdentity, assemblyInfo);
- foreach (var assemblySystem in AssemblySystems)
- {
- await assemblySystem.Load(assemblyIdentity);
- }
- }
- }
-
- ///
- /// 卸载程序集
- ///
- ///
- public static async FTask UnLoadAssembly(System.Reflection.Assembly assembly)
- {
- var assemblyIdentity = AssemblyIdentity(assembly);
-
- if (!AssemblyList.Remove(assemblyIdentity, out var assemblyInfo))
- {
- return;
- }
-
- assemblyInfo.Unload();
- foreach (var assemblySystem in AssemblySystems)
- {
- await assemblySystem.OnUnLoad(assemblyIdentity);
- }
- }
-
- ///
- /// 将AssemblySystem接口的object注册到程序集管理中心
- ///
- ///
- public static async FTask Register(object obj)
- {
- if (obj is not IAssembly assemblySystem)
- {
- return;
- }
-#if FANTASY_WEBGL
- AssemblySystems.Add(assemblySystem);
-#else
- AssemblySystems.Enqueue(assemblySystem);
-#endif
- foreach (var (assemblyIdentity, _) in AssemblyList)
- {
- await assemblySystem.Load(assemblyIdentity);
- }
- }
-
- ///
- /// 程序集管理中心卸载注册的Load、ReLoad、UnLoad的接口
- ///
- ///
- public static void UnRegister(object obj)
- {
- if (obj is not IAssembly assemblySystem)
- {
- return;
- }
-#if FANTASY_WEBGL
- AssemblySystems.Remove(assemblySystem);
-#else
- var count = AssemblySystems.Count;
-
- for (var i = 0; i < count; i++)
- {
- if (!AssemblySystems.TryDequeue(out var removeAssemblySystem))
- {
- continue;
- }
-
- if (removeAssemblySystem == assemblySystem)
- {
- break;
- }
-
- AssemblySystems.Enqueue(removeAssemblySystem);
- }
-#endif
- }
-
- ///
- /// 获取所有已加载程序集中的所有类型。
- ///
- /// 所有已加载程序集中的类型。
- public static IEnumerable ForEach()
- {
- foreach (var (_, assemblyInfo) in AssemblyList)
- {
- foreach (var type in assemblyInfo.AssemblyTypeList)
- {
- yield return type;
- }
- }
- }
-
- ///
- /// 获取指定程序集中的所有类型。
- ///
- /// 程序集唯一标识。
- /// 指定程序集中的类型。
- public static IEnumerable ForEach(long assemblyIdentity)
- {
- if (!AssemblyList.TryGetValue(assemblyIdentity, out var assemblyInfo))
- {
- yield break;
- }
-
- foreach (var type in assemblyInfo.AssemblyTypeList)
- {
- yield return type;
- }
- }
-
- ///
- /// 获取所有已加载程序集中实现指定类型的所有类型。
- ///
- /// 要查找的基类或接口类型。
- /// 所有已加载程序集中实现指定类型的类型。
- public static IEnumerable ForEach(Type findType)
- {
- foreach (var (_, assemblyInfo) in AssemblyList)
- {
- if (!assemblyInfo.AssemblyTypeGroupList.TryGetValue(findType, out var assemblyLoad))
- {
- continue;
- }
-
- foreach (var type in assemblyLoad)
- {
- yield return type;
- }
- }
- }
-
- ///
- /// 获取指定程序集中实现指定类型的所有类型。
- ///
- /// 程序集唯一标识。
- /// 要查找的基类或接口类型。
- /// 指定程序集中实现指定类型的类型。
- public static IEnumerable ForEach(long assemblyIdentity, Type findType)
- {
- if (!AssemblyList.TryGetValue(assemblyIdentity, out var assemblyInfo))
- {
- yield break;
- }
-
- if (!assemblyInfo.AssemblyTypeGroupList.TryGetValue(findType, out var assemblyLoad))
- {
- yield break;
- }
-
- foreach (var type in assemblyLoad)
- {
- yield return type;
- }
- }
-
- ///
- /// 获取指定程序集的实例。
- ///
- /// 程序集名称。
- /// 指定程序集的实例,如果未加载则返回 null。
- public static System.Reflection.Assembly GetAssembly(long assemblyIdentity)
- {
- return !AssemblyList.TryGetValue(assemblyIdentity, out var assemblyInfo) ? null : assemblyInfo.Assembly;
- }
-
- ///
- /// 获取当前框架注册的Assembly
- ///
- ///
- public static IEnumerable ForEachAssembly
- {
- get
- {
- foreach (var (_, assemblyInfo) in AssemblyList)
- {
- yield return assemblyInfo.Assembly;
- }
- }
- }
-
- ///
- /// 根据Assembly的强命名计算唯一标识。
- ///
- ///
- ///
- private static long AssemblyIdentity(System.Reflection.Assembly assembly)
- {
- return HashCodeHelper.ComputeHash64(assembly.GetName().Name);
- }
-
- ///
- /// 释放资源,卸载所有加载的程序集。
- ///
- public static void Dispose()
- {
- DisposeAsync().Coroutine();
- }
-
- private static async FTask DisposeAsync()
- {
- foreach (var (_, assemblyInfo) in AssemblyList.ToArray())
- {
- await UnLoadAssembly(assemblyInfo.Assembly);
- }
-
- AssemblyList.Clear();
- AssemblySystems.Clear();
- }
- }
-}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/IAssembly.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/IAssembly.cs
deleted file mode 100644
index 185e037..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/IAssembly.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using Fantasy.Async;
-
-namespace Fantasy.Assembly
-{
- ///
- /// 实现这个接口、会再程序集首次加载、卸载、重载的时候调用
- ///
- public interface IAssembly : IDisposable
- {
- ///
- /// 程序集加载时调用
- ///
- /// 程序集标识
- public FTask Load(long assemblyIdentity);
- ///
- /// 程序集重新加载的时候调用
- ///
- /// 程序集标识
- public FTask ReLoad(long assemblyIdentity);
- ///
- /// 卸载的时候调用
- ///
- /// 程序集标识
- public FTask OnUnLoad(long assemblyIdentity);
- }
-}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IAssemblyLifecycle.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IAssemblyLifecycle.cs
new file mode 100644
index 0000000..57d7ad9
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IAssemblyLifecycle.cs
@@ -0,0 +1,29 @@
+using System;
+using Fantasy.Async;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 程序集生命周期回调接口
+ /// 实现此接口的类型可以接收程序集的加载、卸载、重载事件通知
+ /// 通过 AssemblySystem.Add() 注册后,在程序集状态变化时会自动调用对应的生命周期方法
+ ///
+ internal interface IAssemblyLifecycle
+ {
+ ///
+ /// 程序集加载或重载时调用
+ /// 当新的程序集被加载到框架中时触发此回调,重新加载已存在的程序集时也会调用
+ ///
+ /// 程序集清单对象,包含程序集的元数据和注册器
+ /// 异步任务
+ FTask OnLoad(AssemblyManifest assemblyManifest);
+
+ ///
+ /// 程序集卸载时调用
+ /// 当程序集从框架中卸载时触发此回调,应在此方法中清理该程序集相关的资源
+ ///
+ /// 程序集清单对象,包含程序集的元数据和注册器
+ /// 异步任务
+ FTask OnUnload(AssemblyManifest assemblyManifest);
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEntitySystemRegistrar.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEntitySystemRegistrar.cs
new file mode 100644
index 0000000..8c2f8c7
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEntitySystemRegistrar.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using Fantasy.Entitas;
+using Fantasy.Entitas.Interface;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 实体系统注册器接口
+ /// 由 Source Generator 自动生成实现类,用于在程序集加载时注册实体系统
+ ///
+ public interface IEntitySystemRegistrar
+ {
+#if FANTASY_NET
+ ///
+ /// 注册该程序集中的所有实体系统
+ ///
+ /// Awake 系统容器
+ /// Update 系统容器
+ /// Destroy 系统容器
+ /// Deserialize 系统容器
+ void RegisterSystems(
+ Dictionary> awakeSystems,
+ Dictionary> updateSystems,
+ Dictionary> destroySystems,
+ Dictionary> deserializeSystems);
+
+ ///
+ /// 取消注册该程序集中的所有实体系统(热重载卸载时调用)
+ ///
+ /// Awake 系统容器
+ /// Update 系统容器
+ /// Destroy 系统容器
+ /// Deserialize 系统容器
+ void UnRegisterSystems(
+ Dictionary> awakeSystems,
+ Dictionary> updateSystems,
+ Dictionary> destroySystems,
+ Dictionary> deserializeSystems);
+#endif
+#if FANTASY_UNITY
+ ///
+ /// 注册该程序集中的所有实体系统
+ ///
+ /// Awake 系统容器
+ /// Update 系统容器
+ /// Destroy 系统容器
+ /// Deserialize 系统容器
+ /// LateUpdate 系统容器
+ void RegisterSystems(
+ Dictionary> awakeSystems,
+ Dictionary> updateSystems,
+ Dictionary> destroySystems,
+ Dictionary> deserializeSystems,
+ Dictionary> lateUpdateSystems);
+
+ ///
+ /// 取消注册该程序集中的所有实体系统(热重载卸载时调用)
+ ///
+ /// Awake 系统容器
+ /// Update 系统容器
+ /// Destroy 系统容器
+ /// Deserialize 系统容器
+ /// LateUpdate 系统容器
+ void UnRegisterSystems(
+ Dictionary> awakeSystems,
+ Dictionary> updateSystems,
+ Dictionary> destroySystems,
+ Dictionary> deserializeSystems,
+ Dictionary> lateUpdateSystems);
+#endif
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEntityTypeCollectionRegistrar.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEntityTypeCollectionRegistrar.cs
new file mode 100644
index 0000000..32297d8
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEntityTypeCollectionRegistrar.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 实体类型集合注册器接口
+ /// 由 Source Generator 自动生成实现类,用于收集和提供程序集中定义的所有实体类型
+ ///
+ public interface IEntityTypeCollectionRegistrar
+ {
+ ///
+ /// 获取该程序集中定义的所有实体类型
+ /// 返回继承自 Entity 的所有类型列表
+ ///
+ /// 实体类型列表
+ List GetEntityTypes();
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEventSystemRegistrar.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEventSystemRegistrar.cs
new file mode 100644
index 0000000..1fdd602
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IEventSystemRegistrar.cs
@@ -0,0 +1,35 @@
+using System;
+using Fantasy.DataStructure.Collection;
+using Fantasy.Event;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 事件系统注册器接口
+ /// 由 Source Generator 自动生成实现类,用于在程序集加载时注册事件系统
+ ///
+ public interface IEventSystemRegistrar : IDisposable
+ {
+ ///
+ /// 注册该程序集中的所有事件系统
+ ///
+ /// 同步事件容器
+ /// 异步事件容器
+ /// 领域事件容器
+ void RegisterSystems(
+ OneToManyList events,
+ OneToManyList asyncEvents,
+ OneToManyList sphereEvents);
+
+ ///
+ /// 取消注册该程序集中的所有事件系统(热重载卸载时调用)
+ ///
+ /// 同步事件容器
+ /// 异步事件容器
+ /// 领域事件容器
+ void UnRegisterSystems(
+ OneToManyList events,
+ OneToManyList asyncEvents,
+ OneToManyList sphereEvents);
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IMessageHandlerResolver.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IMessageHandlerResolver.cs
new file mode 100644
index 0000000..9a12fa1
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/IMessageHandlerResolver.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using Fantasy.DataStructure.Dictionary;
+using Fantasy.Entitas;
+using Fantasy.Network;
+using Fantasy.Network.Interface;
+using Fantasy.Async;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 消息分发器注册器接口
+ /// 由 Source Generator 自动生成实现类,用于在程序集加载时注册网络消息处理器
+ ///
+ public interface IMessageHandlerResolver
+ {
+ ///
+ ///
+ ///
+ ///
+ int GetMessageHandlerCount();
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ bool MessageHandler(Session session, uint rpcId, uint protocolCode, object message);
+#if FANTASY_NET
+ ///
+ ///
+ ///
+ ///
+ int GetRouteMessageHandlerCount();
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ FTask RouteMessageHandler(Session session, Entity entity, uint rpcId, uint protocolCode, object message);
+#endif
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolOpCodeResolver.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolOpCodeResolver.cs
new file mode 100644
index 0000000..6251037
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolOpCodeResolver.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 网络协议 OpCode 解析器接口
+ /// 用于通过生成的 switch 表达式实现高性能的 OpCode 到 Type 的解析
+ ///
+ ///
+ /// 此接口由 SourceGenerator 自动生成的类实现。
+ /// 每个包含网络协议的程序集都会生成自己的解析器实现。
+ /// 生成的实现使用 switch 表达式而不是字典查找,以获得更好的性能。
+ ///
+ public interface INetworkProtocolOpCodeResolver
+ {
+ ///
+ /// 获取当前OpCode数量
+ ///
+ /// 返回对应的OpCode数量
+ int GetOpCodeCount();
+ ///
+ /// 获取当前RouteType数量
+ ///
+ /// 返回对应的RouteType数量
+ int GetCustomRouteTypeCount();
+ ///
+ /// 根据指定的 OpCode 获取对应的 Type
+ ///
+ /// 网络协议操作码
+ /// OpCode 对应的类型;如果未找到则返回 null
+ Type GetOpCodeType(uint opCode);
+ ///
+ /// 根据指定的 OpCode 获取对应的 CustomRouteType
+ ///
+ /// 网络协议操作码
+ /// OpCode 对应的CustomRouteType;如果未找到则返回 null
+ int? GetCustomRouteType(uint opCode);
+
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolRegistrar.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolRegistrar.cs
new file mode 100644
index 0000000..24b8cb0
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolRegistrar.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// NetworkProtocol 类型注册器接口
+ /// 由 Source Generator 自动生成实现类,用于收集和提供程序集中需要 NetworkProtocol 序列化的类型
+ ///
+ public interface INetworkProtocolRegistrar
+ {
+ ///
+ /// 获取该程序集中需要 NetworkProtocol 序列化的所有类型
+ /// 返回所有使用 NetworkProtocol 序列化特性标记的类型列表
+ ///
+ /// NetworkProtocol 序列化类型列表
+ List GetNetworkProtocolTypes();
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolResponseTypeResolver.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolResponseTypeResolver.cs
new file mode 100644
index 0000000..0385244
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/INetworkProtocolResponseTypeResolver.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Fantasy.Assembly
+{
+ ///
+ /// 网络协议响应类型解析器接口
+ /// 用于根据 OpCode 解析对应的响应消息类型
+ /// 此接口通常由 NetworkProtocol SourceGenerator 自动生成实现
+ ///
+ public interface INetworkProtocolResponseTypeResolver
+ {
+ ///
+ /// 获取已注册的 Response 总数
+ ///
+ /// 协议系统中可用的 OpCode 数量
+ int GetRequestCount();
+
+ ///
+ /// 获取指定 OpCode 对应的响应消息类型
+ /// 用于在处理网络消息时确定期望的响应类型
+ ///
+ /// 要解析的 OpCode
+ /// 响应消息的类型,如果该 OpCode 没有关联响应类型则返回 null
+ Type GetResponseType(uint opCode);
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/ISeparateTableRegistrar.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/ISeparateTableRegistrar.cs
new file mode 100644
index 0000000..821050e
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Assembly/Interface/ISeparateTableRegistrar.cs
@@ -0,0 +1,34 @@
+#if FANTASY_NET
+namespace Fantasy.Assembly;
+
+///
+/// 分表注册器接口,用于自动注册标记了 SeparateTableAttribute 的实体类型。
+/// 通过 Source Generator 自动生成实现类,替代运行时反射,提升性能。
+///
+public interface ISeparateTableRegistrar
+{
+ ///
+ /// 分表信息记录,包含父实体类型、子实体类型和数据库集合名称。
+ ///
+ /// 父实体的类型,表示子实体属于哪个父实体。
+ /// 子实体的类型,即标记了 SeparateTableAttribute 的实体类型。
+ /// 在数据库中使用的集合名称。
+ public sealed record SeparateTableInfo(Type RootType, Type EntityType, string TableName);
+
+ ///
+ /// 注册所有分表信息。
+ /// 返回包含所有标记了 SeparateTableAttribute 的实体及其配置信息的列表。
+ ///
+ /// 分表信息列表。
+ List Register();
+
+ ///
+ /// 反注册所有分表信息。
+ /// 返回需要移除的分表信息列表。
+ ///
+ /// 分表信息列表。
+ List UnRegister();
+}
+
+
+#endif
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EntityComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EntityComponent.cs
deleted file mode 100644
index 67dc9ef..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EntityComponent.cs
+++ /dev/null
@@ -1,523 +0,0 @@
-// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.InteropServices;
-using Fantasy.Assembly;
-using Fantasy.Async;
-using Fantasy.DataStructure.Collection;
-using Fantasy.Entitas;
-using Fantasy.Entitas.Interface;
-using Fantasy.Helper;
-#pragma warning disable CS8602 // Dereference of a possibly null reference.
-#pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
-
-#pragma warning disable CS8604 // Possible null reference argument.
-#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
-namespace Fantasy.Entitas
-{
- internal sealed class UpdateQueueInfo
- {
- public bool IsStop;
- public readonly Type Type;
- public readonly long RunTimeId;
-
- public UpdateQueueInfo(Type type, long runTimeId)
- {
- Type = type;
- IsStop = false;
- RunTimeId = runTimeId;
- }
- }
-
- internal sealed class FrameUpdateQueueInfo
- {
- public readonly Type Type;
- public readonly long RunTimeId;
-
- public FrameUpdateQueueInfo(Type type, long runTimeId)
- {
- Type = type;
- RunTimeId = runTimeId;
- }
- }
-
- internal struct CustomEntitiesSystemKey : IEquatable
- {
- public int CustomEventType { get; }
- public Type EntitiesType { get; }
- public CustomEntitiesSystemKey(int customEventType, Type entitiesType)
- {
- CustomEventType = customEventType;
- EntitiesType = entitiesType;
- }
- public bool Equals(CustomEntitiesSystemKey other)
- {
- return CustomEventType == other.CustomEventType && EntitiesType == other.EntitiesType;
- }
-
- public override bool Equals(object obj)
- {
- return obj is CustomEntitiesSystemKey other && Equals(other);
- }
-
- public override int GetHashCode()
- {
- return HashCode.Combine(CustomEventType, EntitiesType);
- }
- }
-
- ///
- /// Entity管理组件
- ///
-#if FANTASY_UNITY
- public sealed class EntityComponent : Entity, ISceneUpdate, ISceneLateUpdate, IAssembly
-#else
- public sealed class EntityComponent : Entity, ISceneUpdate, IAssembly
-#endif
- {
- private readonly OneToManyList _assemblyList = new();
- private readonly OneToManyList _assemblyHashCodes = new();
-
- private readonly Dictionary _awakeSystems = new();
- private readonly Dictionary _updateSystems = new();
- private readonly Dictionary _destroySystems = new();
- private readonly Dictionary _deserializeSystems = new();
-
- private readonly OneToManyList _assemblyCustomSystemList = new();
- private readonly Dictionary _customEntitiesSystems = new Dictionary();
-
- private readonly Dictionary _hashCodes = new Dictionary();
- private readonly Queue _updateQueue = new Queue();
-
- private readonly Dictionary _updateQueueDic = new Dictionary();
-#if FANTASY_UNITY
- private readonly Dictionary _lateUpdateSystems = new();
- private readonly Queue _lateUpdateQueue = new Queue();
- private readonly Dictionary _lateUpdateQueueDic = new Dictionary();
-#endif
-
- internal async FTask Initialize()
- {
- await AssemblySystem.Register(this);
- return this;
- }
-
- #region Assembly
-
- public FTask Load(long assemblyIdentity)
- {
- var task = FTask.Create(false);
- Scene?.ThreadSynchronizationContext.Post(() =>
- {
- LoadInner(assemblyIdentity);
- task.SetResult();
- });
- return task;
- }
-
- public FTask ReLoad(long assemblyIdentity)
- {
- var task = FTask.Create(false);
- Scene?.ThreadSynchronizationContext.Post(() =>
- {
- OnUnLoadInner(assemblyIdentity);
- LoadInner(assemblyIdentity);
- task.SetResult();
- });
-
- return task;
- }
-
- public FTask OnUnLoad(long assemblyIdentity)
- {
- var task = FTask.Create(false);
- Scene?.ThreadSynchronizationContext.Post(() =>
- {
- OnUnLoadInner(assemblyIdentity);
- task.SetResult();
- });
- return task;
- }
-
- private void LoadInner(long assemblyIdentity)
- {
- foreach (var entityType in AssemblySystem.ForEach(assemblyIdentity, typeof(IEntity)))
- {
- _hashCodes.Add(entityType, HashCodeHelper.ComputeHash64(entityType.FullName));
- _assemblyHashCodes.Add(assemblyIdentity, entityType);
- }
-
- foreach (var entitiesSystemType in AssemblySystem.ForEach(assemblyIdentity, typeof(IEntitiesSystem)))
- {
- Type entitiesType = null;
- var entity = Activator.CreateInstance(entitiesSystemType);
-
- switch (entity)
- {
- case IAwakeSystem iAwakeSystem:
- {
- entitiesType = iAwakeSystem.EntitiesType();
- _awakeSystems.Add(entitiesType, iAwakeSystem);
- break;
- }
- case IDestroySystem iDestroySystem:
- {
- entitiesType = iDestroySystem.EntitiesType();
- _destroySystems.Add(entitiesType, iDestroySystem);
- break;
- }
- case IDeserializeSystem iDeserializeSystem:
- {
- entitiesType = iDeserializeSystem.EntitiesType();
- _deserializeSystems.Add(entitiesType, iDeserializeSystem);
- break;
- }
- case IUpdateSystem iUpdateSystem:
- {
- entitiesType = iUpdateSystem.EntitiesType();
- _updateSystems.Add(entitiesType, iUpdateSystem);
- break;
- }
-#if FANTASY_UNITY
- case ILateUpdateSystem iLateUpdateSystem:
- {
- entitiesType = iLateUpdateSystem.EntitiesType();
- _lateUpdateSystems.Add(entitiesType, iLateUpdateSystem);
- break;
- }
-#endif
- default:
- {
- Log.Error($"IEntitiesSystem not support type {entitiesSystemType}");
- return;
- }
- }
-
- _assemblyList.Add(assemblyIdentity, entitiesType);
- }
-
- foreach (var customEntitiesSystemType in AssemblySystem.ForEach(assemblyIdentity, typeof(ICustomEntitiesSystem)))
- {
- var entity = (ICustomEntitiesSystem)Activator.CreateInstance(customEntitiesSystemType);
- var customEntitiesSystemKey = new CustomEntitiesSystemKey(entity.CustomEventType, entity.EntitiesType());
- _customEntitiesSystems.Add(customEntitiesSystemKey, entity);
- _assemblyCustomSystemList.Add(assemblyIdentity, customEntitiesSystemKey);
- }
- }
-
- private void OnUnLoadInner(long assemblyIdentity)
- {
- if (_assemblyHashCodes.TryGetValue(assemblyIdentity, out var entityType))
- {
- foreach (var type in entityType)
- {
- _hashCodes.Remove(type);
- }
-
- _assemblyHashCodes.RemoveByKey(assemblyIdentity);
- }
-
- if (_assemblyList.TryGetValue(assemblyIdentity, out var assembly))
- {
- foreach (var type in assembly)
- {
- _awakeSystems.Remove(type);
- _updateSystems.Remove(type);
- _destroySystems.Remove(type);
-#if FANTASY_UNITY
- _lateUpdateSystems.Remove(type);
-#endif
- _deserializeSystems.Remove(type);
- }
-
- _assemblyList.RemoveByKey(assemblyIdentity);
- }
-
- if (_assemblyCustomSystemList.TryGetValue(assemblyIdentity, out var customSystemAssembly))
- {
- foreach (var customEntitiesSystemKey in customSystemAssembly)
- {
- _customEntitiesSystems.Remove(customEntitiesSystemKey);
- }
-
- _assemblyCustomSystemList.RemoveByKey(assemblyIdentity);
- }
- }
-
- #endregion
-
- #region Event
-
- ///
- /// 触发实体的唤醒方法
- ///
- /// 实体对象
- public void Awake(Entity entity)
- {
- if (!_awakeSystems.TryGetValue(entity.Type, out var awakeSystem))
- {
- return;
- }
-
- try
- {
- awakeSystem.Invoke(entity);
- }
- catch (Exception e)
- {
- Log.Error($"{entity.Type.FullName} Error {e}");
- }
- }
-
- ///
- /// 触发实体的销毁方法
- ///
- /// 实体对象
- public void Destroy(Entity entity)
- {
- if (!_destroySystems.TryGetValue(entity.Type, out var system))
- {
- return;
- }
-
- try
- {
- system.Invoke(entity);
- }
- catch (Exception e)
- {
- Log.Error($"{entity.Type.FullName} Destroy Error {e}");
- }
- }
-
- ///
- /// 触发实体的反序列化方法
- ///
- /// 实体对象
- public void Deserialize(Entity entity)
- {
- if (!_deserializeSystems.TryGetValue(entity.Type, out var system))
- {
- return;
- }
-
- try
- {
- system.Invoke(entity);
- }
- catch (Exception e)
- {
- Log.Error($"{entity.Type.FullName} Deserialize Error {e}");
- }
- }
-
- #endregion
-
- #region CustomEvent
-
- public void CustomSystem(Entity entity, int customEventType)
- {
- var customEntitiesSystemKey = new CustomEntitiesSystemKey(customEventType, entity.Type);
-
- if (!_customEntitiesSystems.TryGetValue(customEntitiesSystemKey, out var system))
- {
- return;
- }
-
- try
- {
- system.Invoke(entity);
- }
- catch (Exception e)
- {
- Log.Error($"{entity.Type.FullName} CustomSystem Error {e}");
- }
- }
-
- #endregion
-
- #region Update
-
- ///
- /// 将实体加入Update队列,准备进行Update
- ///
- /// 实体对象
- public void StartUpdate(Entity entity)
- {
- var type = entity.Type;
- var entityRuntimeId = entity.RuntimeId;
-
- if (!_updateSystems.ContainsKey(type))
- {
- return;
- }
-
- var updateQueueInfo = new UpdateQueueInfo(type, entityRuntimeId);
- _updateQueue.Enqueue(updateQueueInfo);
- _updateQueueDic.Add(entityRuntimeId, updateQueueInfo);
- }
-
- ///
- /// 停止实体Update
- ///
- /// 实体对象
- public void StopUpdate(Entity entity)
- {
- if (!_updateQueueDic.Remove(entity.RuntimeId, out var updateQueueInfo))
- {
- return;
- }
-
- updateQueueInfo.IsStop = true;
- }
-
- ///
- /// 执行实体系统的Update
- ///
- public void Update()
- {
- var updateQueueCount = _updateQueue.Count;
-
- while (updateQueueCount-- > 0)
- {
- var updateQueueStruct = _updateQueue.Dequeue();
-
- if (updateQueueStruct.IsStop)
- {
- continue;
- }
-
- if (!_updateSystems.TryGetValue(updateQueueStruct.Type, out var updateSystem))
- {
- continue;
- }
-
- var entity = Scene.GetEntity(updateQueueStruct.RunTimeId);
-
- if (entity == null || entity.IsDisposed)
- {
- _updateQueueDic.Remove(updateQueueStruct.RunTimeId);
- continue;
- }
-
- _updateQueue.Enqueue(updateQueueStruct);
-
- try
- {
- updateSystem.Invoke(entity);
- }
- catch (Exception e)
- {
- Log.Error($"{updateQueueStruct.Type.FullName} Update Error {e}");
- }
- }
- }
-
- #endregion
-
-#if FANTASY_UNITY
- #region LateUpdate
-
- ///
- /// 将实体加入LateUpdate队列,准备进行LateUpdate
- ///
- /// 实体对象
- public void StartLateUpdate(Entity entity)
- {
- var type = entity.Type;
- var entityRuntimeId = entity.RuntimeId;
-
- if (!_lateUpdateSystems.ContainsKey(type))
- {
- return;
- }
-
- var updateQueueInfo = new UpdateQueueInfo(type, entityRuntimeId);
- _lateUpdateQueue.Enqueue(updateQueueInfo);
- _lateUpdateQueueDic.Add(entityRuntimeId, updateQueueInfo);
- }
-
- ///
- /// 停止实体进行LateUpdate
- ///
- /// 实体对象
- public void StopLateUpdate(Entity entity)
- {
- if (!_lateUpdateQueueDic.Remove(entity.RuntimeId, out var updateQueueInfo))
- {
- return;
- }
-
- updateQueueInfo.IsStop = true;
- }
-
- public void LateUpdate()
- {
- var lateUpdateQueue = _lateUpdateQueue.Count;
-
- while (lateUpdateQueue-- > 0)
- {
- var lateUpdateQueueStruct = _lateUpdateQueue.Dequeue();
-
- if (lateUpdateQueueStruct.IsStop)
- {
- continue;
- }
-
- if (!_lateUpdateSystems.TryGetValue(lateUpdateQueueStruct.Type, out var lateUpdateSystem))
- {
- continue;
- }
-
- var entity = Scene.GetEntity(lateUpdateQueueStruct.RunTimeId);
-
- if (entity == null || entity.IsDisposed)
- {
- _lateUpdateQueueDic.Remove(lateUpdateQueueStruct.RunTimeId);
- continue;
- }
-
- _lateUpdateQueue.Enqueue(lateUpdateQueueStruct);
-
- try
- {
- lateUpdateSystem.Invoke(entity);
- }
- catch (Exception e)
- {
- Log.Error($"{lateUpdateQueueStruct.Type.FullName} Update Error {e}");
- }
- }
- }
- #endregion
-#endif
- public long GetHashCode(Type type)
- {
- return _hashCodes[type];
- }
-
- ///
- /// 释放实体系统管理器资源
- ///
- public override void Dispose()
- {
- _updateQueue.Clear();
- _updateQueueDic.Clear();
-#if FANTASY_UNITY
- _lateUpdateQueue.Clear();
- _lateUpdateQueueDic.Clear();
- _lateUpdateSystems.Clear();
-#endif
- _assemblyList.Clear();
- _awakeSystems.Clear();
- _updateSystems.Clear();
- _destroySystems.Clear();
- _deserializeSystems.Clear();
-
- AssemblySystem.UnRegister(this);
- base.Dispose();
- }
- }
-}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EntityComponent/EntityComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EntityComponent/EntityComponent.cs
new file mode 100644
index 0000000..cb1ee99
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EntityComponent/EntityComponent.cs
@@ -0,0 +1,476 @@
+using System;
+using System.Collections.Generic;
+using Fantasy.Assembly;
+using Fantasy.Async;
+using Fantasy.Entitas.Interface;
+// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
+// ReSharper disable ForCanBeConvertedToForeach
+#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
+#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.
+#pragma warning disable CS8602 // Dereference of a possibly null reference.
+
+namespace Fantasy.Entitas
+{
+ ///
+ /// 更新队列节点,用于存储需要每帧更新的实体信息
+ ///
+ internal sealed class UpdateQueueNode
+ {
+ ///
+ /// 实体类型
+ ///
+ public long TypeHashCode;
+ ///
+ /// 实体运行时ID
+ ///
+ public long RunTimeId;
+ }
+ ///
+ /// 实体组件系统管理器,负责管理所有实体的生命周期和系统调度
+ /// 支持程序集热重载、实体生命周期事件和每帧更新循环
+ ///
+#if FANTASY_UNITY
+ public sealed class EntityComponent : Entity, ISceneUpdate, ISceneLateUpdate, IAssemblyLifecycle
+#else
+ public sealed class EntityComponent : Entity, ISceneUpdate, IAssemblyLifecycle
+#endif
+ {
+ ///
+ /// 已加载的程序集清单ID集合
+ ///
+ private readonly HashSet _assemblyManifests = new();
+ ///
+ /// 实体唤醒系统字典,Key为实体类型TypeHashCode,Value为对应的唤醒系统
+ ///
+ private readonly Dictionary> _awakeSystems = new();
+ ///
+ /// 实体更新系统字典,Key为实体类型TypeHashCode,Value为对应的更新系统
+ ///
+ private readonly Dictionary> _updateSystems = new();
+ ///
+ /// 实体销毁系统字典,Key为实体类型TypeHashCode,Value为对应的销毁系统
+ ///
+ private readonly Dictionary> _destroySystems = new();
+ ///
+ /// 实体反序列化系统字典,Key为实体类型TypeHashCode,Value为对应的反序列化系统
+ ///
+ private readonly Dictionary> _deserializeSystems = new();
+ ///
+ /// 更新队列,使用链表实现循环遍历和O(1)删除
+ ///
+ private readonly LinkedList _updateQueue = new();
+ ///
+ /// 更新节点字典,Key为实体RuntimeId,Value为对应的链表节点,用于快速查找和删除
+ ///
+ private readonly Dictionary> _updateNodes = new();
+#if FANTASY_UNITY
+ private readonly Dictionary> _lateUpdateSystems = new();
+ ///
+ /// Late更新队列,使用链表实现循环遍历和O(1)删除
+ ///
+ private readonly LinkedList _lateUpdateQueue = new();
+ ///
+ /// Late更新节点字典,Key为实体RuntimeId,Value为对应的链表节点,用于快速查找和删除
+ ///
+ private readonly Dictionary> _lateUpdateNodes = new();
+#endif
+ ///
+ /// 销毁时会清理组件里的所有数据
+ ///
+ public override void Dispose()
+ {
+ if (IsDisposed)
+ {
+ return;
+ }
+
+ _assemblyManifests.Clear();
+ _awakeSystems.Clear();
+ _updateSystems.Clear();
+ _destroySystems.Clear();
+
+ _updateQueue.Clear();
+ _updateNodes.Clear();
+#if FANTASY_UNITY
+ _lateUpdateSystems.Clear();
+ _lateUpdateQueue.Clear();
+ _lateUpdateNodes.Clear();
+#endif
+ AssemblyLifecycle.Remove(this);
+ base.Dispose();
+ }
+
+ #region AssemblyManifest
+
+ ///
+ /// 初始化EntityComponent,将其注册到程序集系统中
+ ///
+ /// 返回初始化后的EntityComponent实例
+ internal async FTask Initialize()
+ {
+ await AssemblyLifecycle.Add(this);
+ return this;
+ }
+
+ ///
+ /// 加载程序集,注册该程序集中的所有实体系统
+ /// 支持热重载:如果程序集已加载,会先卸载再重新加载
+ ///
+ /// 程序集清单对象,包含程序集的元数据和注册器
+ /// 异步任务
+ public FTask OnLoad(AssemblyManifest assemblyManifest)
+ {
+ var task = FTask.Create(false);
+ var assemblyManifestId = assemblyManifest.AssemblyManifestId;
+ Scene?.ThreadSynchronizationContext.Post(() =>
+ {
+ // 如果程序集已加载,先卸载旧的
+ if (_assemblyManifests.Contains(assemblyManifestId))
+ {
+ OnUnLoadInner(assemblyManifest);
+ }
+#if FANTASY_NET
+ assemblyManifest.EntitySystemRegistrar.RegisterSystems(
+ _awakeSystems,
+ _updateSystems,
+ _destroySystems,
+ _deserializeSystems);
+#endif
+#if FANTASY_UNITY
+ assemblyManifest.EntitySystemRegistrar.RegisterSystems(
+ _awakeSystems,
+ _updateSystems,
+ _destroySystems,
+ _deserializeSystems,
+ _lateUpdateSystems);
+#endif
+ _assemblyManifests.Add(assemblyManifestId);
+ task.SetResult();
+ });
+ return task;
+ }
+
+ ///
+ /// 卸载程序集,取消注册该程序集中的所有实体系统
+ ///
+ /// 程序集清单对象,包含程序集的元数据和注册器
+ /// 异步任务
+ public FTask OnUnload(AssemblyManifest assemblyManifest)
+ {
+ var task = FTask.Create(false);
+ Scene?.ThreadSynchronizationContext.Post(() =>
+ {
+ OnUnLoadInner(assemblyManifest);
+ task.SetResult();
+ });
+ return task;
+ }
+
+ ///
+ /// 卸载程序集的内部实现
+ /// 会清理该程序集注册的所有系统,并移除更新队列中对应的实体
+ ///
+ /// 程序集清单对象,包含程序集的元数据和注册器
+ private void OnUnLoadInner(AssemblyManifest assemblyManifest)
+ {
+#if FANTASY_NET
+ assemblyManifest.EntitySystemRegistrar.UnRegisterSystems(
+ _awakeSystems,
+ _updateSystems,
+ _destroySystems,
+ _deserializeSystems);
+#endif
+#if FANTASY_UNITY
+ assemblyManifest.EntitySystemRegistrar.UnRegisterSystems(
+ _awakeSystems,
+ _updateSystems,
+ _destroySystems,
+ _deserializeSystems,
+ _lateUpdateSystems);
+#endif
+ _assemblyManifests.Remove(assemblyManifest.AssemblyManifestId);
+ // 清理更新队列中已失效的节点(系统被卸载后,对应实体的更新系统不再存在)
+ var node = _updateQueue.First;
+ while (node != null)
+ {
+ var next = node.Next;
+ if (!_updateSystems.ContainsKey(node.Value.TypeHashCode))
+ {
+ _updateQueue.Remove(node);
+ _updateNodes.Remove(node.Value.RunTimeId);
+ }
+ node = next;
+ }
+#if FANTASY_UNITY
+ var lateNode = _lateUpdateQueue.First;
+ while (lateNode != null)
+ {
+ var next = lateNode.Next;
+ if (!_lateUpdateSystems.ContainsKey(lateNode.Value.TypeHashCode))
+ {
+ _lateUpdateQueue.Remove(lateNode);
+ _lateUpdateNodes.Remove(lateNode.Value.RunTimeId);
+ }
+ lateNode = next;
+ }
+#endif
+ }
+
+ #endregion
+
+ #region Event
+
+ ///
+ /// 触发实体的唤醒事件,调用对应的AwakeSystem
+ ///
+ /// 需要唤醒的实体
+ public void Awake(Entity entity)
+ {
+ if (!_awakeSystems.TryGetValue(entity.TypeHashCode, out var awakeSystem))
+ {
+ return;
+ }
+
+ try
+ {
+ awakeSystem(entity);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"{entity.Type.FullName} Error {e}");
+ }
+ }
+
+ ///
+ /// 触发实体的销毁事件,调用对应的DestroySystem
+ ///
+ /// 需要销毁的实体
+ public void Destroy(Entity entity)
+ {
+ if (!_destroySystems.TryGetValue(entity.TypeHashCode, out var system))
+ {
+ return;
+ }
+
+ try
+ {
+ system(entity);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"{entity.Type.FullName} Destroy Error {e}");
+ }
+ }
+
+ ///
+ /// 触发实体的反序列化事件,调用对应的DeserializeSystem
+ ///
+ /// 需要反序列化的实体
+ public void Deserialize(Entity entity)
+ {
+ if (!_deserializeSystems.TryGetValue(entity.TypeHashCode, out var system))
+ {
+ return;
+ }
+
+ try
+ {
+ system(entity);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"{entity.Type.FullName} Deserialize Error {e}");
+ }
+ }
+
+ #endregion
+
+ #region Update
+
+ ///
+ /// 注册实体到每帧更新循环
+ /// 实体将在每帧Update时执行对应的UpdateSystem
+ ///
+ /// 需要注册更新的实体
+ public void RegisterUpdate(Entity entity)
+ {
+ var typeHashCode = entity.TypeHashCode;
+ // 检查该实体类型是否有对应的更新系统
+ if (!_updateSystems.ContainsKey(typeHashCode))
+ {
+ return;
+ }
+
+ var runtimeId = entity.RuntimeId;
+ // 防止重复注册
+ if (_updateNodes.ContainsKey(runtimeId))
+ {
+ return;
+ }
+
+ // 创建节点并加入链表尾部
+ var nodeData = new UpdateQueueNode { TypeHashCode = typeHashCode, RunTimeId = runtimeId };
+ var node = _updateQueue.AddLast(nodeData);
+ _updateNodes.Add(runtimeId, node);
+ }
+
+ ///
+ /// 从每帧更新循环中注销实体
+ /// 实体将不再执行UpdateSystem
+ ///
+ /// 需要注销更新的实体
+ public void UnregisterUpdate(Entity entity)
+ {
+ if (!_updateNodes.Remove(entity.RuntimeId, out var node))
+ {
+ return;
+ }
+
+ // 利用链表节点实现O(1)时间复杂度删除
+ _updateQueue.Remove(node);
+ }
+
+ ///
+ /// 每帧更新循环,遍历所有已注册的实体并调用对应的UpdateSystem
+ /// 使用链表实现循环队列,已删除的实体会自动清理
+ ///
+ public void Update()
+ {
+ var scene = Scene;
+ var node = _updateQueue.First;
+ var count = _updateQueue.Count;
+
+ // 遍历当前所有节点,count确保只遍历本帧的节点
+ while (count-- > 0 && node != null)
+ {
+ var next = node.Next; // 提前保存下一个节点,防止当前节点被删除
+ var data = node.Value;
+
+ // 检查更新系统是否存在(可能被热重载卸载)
+ if (!_updateSystems.TryGetValue(data.TypeHashCode, out var updateSystem))
+ {
+ node = next;
+ continue;
+ }
+
+ var entity = scene.GetEntity(data.RunTimeId);
+
+ // 如果实体已销毁,自动清理
+ if (entity == null || entity.IsDisposed)
+ {
+ _updateQueue.Remove(node);
+ _updateNodes.Remove(data.RunTimeId);
+ }
+ else
+ {
+ try
+ {
+ updateSystem.Invoke(entity);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"Update Error {e}");
+ }
+ }
+
+ node = next;
+ }
+ }
+
+ #endregion
+
+ #region LateUpdate
+#if FANTASY_UNITY
+ ///
+ /// 注册实体到每帧更新循环
+ /// 实体将在每帧LateUUpdate时执行对应的LateUUpdateSystem
+ ///
+ /// 需要注册更新的实体
+ public void RegisterLateUpdate(Entity entity)
+ {
+ var typeHashCode = entity.TypeHashCode;
+ // 检查该实体类型是否有对应的更新系统
+ if (!_lateUpdateSystems.ContainsKey(typeHashCode))
+ {
+ return;
+ }
+
+ var runtimeId = entity.RuntimeId;
+ // 防止重复注册
+ if (_lateUpdateNodes.ContainsKey(runtimeId))
+ {
+ return;
+ }
+
+ // 创建节点并加入链表尾部
+ var nodeData = new UpdateQueueNode { TypeHashCode = typeHashCode, RunTimeId = runtimeId };
+ var node = _lateUpdateQueue.AddLast(nodeData);
+ _lateUpdateNodes.Add(runtimeId, node);
+ }
+
+ ///
+ /// 从每帧更新循环中注销实体
+ /// 实体将不再执行LateUpdateSystem
+ ///
+ /// 需要注销更新的实体
+ public void UnregisterLateUpdate(Entity entity)
+ {
+ if (!_lateUpdateNodes.Remove(entity.RuntimeId, out var node))
+ {
+ return;
+ }
+
+ // 利用链表节点实现O(1)时间复杂度删除
+ _lateUpdateQueue.Remove(node);
+ }
+
+ ///
+ /// 每帧更新循环,遍历所有已注册的实体并调用对应的LateUpdateSystem
+ /// 使用链表实现循环队列,已删除的实体会自动清理
+ ///
+ public void LateUpdate()
+ {
+ var scene = Scene;
+ var node = _lateUpdateQueue.First;
+ var count = _lateUpdateQueue.Count;
+
+ // 遍历当前所有节点,count确保只遍历本帧的节点
+ while (count-- > 0 && node != null)
+ {
+ var next = node.Next; // 提前保存下一个节点,防止当前节点被删除
+ var data = node.Value;
+
+ // 检查更新系统是否存在(可能被热重载卸载)
+ if (!_lateUpdateSystems.TryGetValue(data.TypeHashCode, out var lateUpdateSystem))
+ {
+ node = next;
+ continue;
+ }
+
+ var entity = scene.GetEntity(data.RunTimeId);
+
+ // 如果实体已销毁,自动清理
+ if (entity == null || entity.IsDisposed)
+ {
+ _lateUpdateQueue.Remove(node);
+ _lateUpdateNodes.Remove(data.RunTimeId);
+ }
+ else
+ {
+ try
+ {
+ lateUpdateSystem.Invoke(entity);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"Update Error {e}");
+ }
+ }
+
+ node = next;
+ }
+ }
+#endif
+ #endregion
+ }
+}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EventComponent/EventComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EventComponent/EventComponent.cs
index 30ca61e..4a106e5 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EventComponent/EventComponent.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EventComponent/EventComponent.cs
@@ -1,129 +1,108 @@
using System;
-using System.Reflection;
+using System.Collections.Generic;
using Fantasy.Assembly;
using Fantasy.Async;
using Fantasy.DataStructure.Collection;
using Fantasy.Entitas;
-
-// ReSharper disable PossibleMultipleEnumeration
-#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
// ReSharper disable MethodOverloadWithOptionalParameter
namespace Fantasy.Event
{
- internal sealed class EventCache
+ ///
+ /// 事件组件系统,负责管理和调度所有事件
+ ///
+ public sealed class EventComponent : Entity, IAssemblyLifecycle
{
- public readonly Type EnventType;
- public readonly object Obj;
- public EventCache(Type enventType, object obj)
+ private readonly HashSet _assemblyManifests = new();
+ private readonly OneToManyList _events = new();
+ private readonly OneToManyList _asyncEvents = new();
+ private readonly OneToManyList _sphereEvents = new();
+
+ ///
+ /// 销毁时会清理组件里的所有数据
+ ///
+ public override void Dispose()
{
- EnventType = enventType;
- Obj = obj;
+ if (IsDisposed)
+ {
+ return;
+ }
+
+ _assemblyManifests.Clear();
+ _events.Clear();
+ _asyncEvents.Clear();
+ _sphereEvents.Clear();
+ AssemblyLifecycle.Remove(this);
+ base.Dispose();
}
- }
- public sealed class EventComponent : Entity, IAssembly
- {
- private readonly OneToManyList _events = new();
- private readonly OneToManyList _asyncEvents = new();
- private readonly OneToManyList _assemblyEvents = new();
- private readonly OneToManyList _assemblyAsyncEvents = new();
+ #region AssemblyManifest
+ ///
+ /// 初始化EventComponent,将其注册到程序集系统中
+ ///
+ /// 返回初始化后的EventComponent实例
internal async FTask Initialize()
{
- await AssemblySystem.Register(this);
+ await AssemblyLifecycle.Add(this);
return this;
}
-
- #region Assembly
-
- public async FTask Load(long assemblyIdentity)
+
+ ///
+ /// 加载程序集,注册该程序集中的所有事件系统
+ /// 支持热重载:如果程序集已加载,会先卸载再重新加载
+ ///
+ /// 程序集清单对象,包含程序集的元数据和注册器
+ /// 异步任务
+ public async FTask OnLoad(AssemblyManifest assemblyManifest)
{
var tcs = FTask.Create(false);
+ var assemblyManifestId = assemblyManifest.AssemblyManifestId;
Scene?.ThreadSynchronizationContext.Post(() =>
{
- LoadInner(assemblyIdentity);
+ // 如果程序集已加载,先卸载旧的
+ if (_assemblyManifests.Contains(assemblyManifestId))
+ {
+ OnUnLoadInner(assemblyManifest);
+ }
+ assemblyManifest.EventSystemRegistrar.RegisterSystems(
+ _events,
+ _asyncEvents,
+ _sphereEvents);
+ _assemblyManifests.Add(assemblyManifestId);
tcs.SetResult();
});
await tcs;
}
-
- public async FTask ReLoad(long assemblyIdentity)
+
+ ///
+ /// 卸载程序集,取消注册该程序集中的所有实体系统
+ ///
+ /// 程序集清单对象,包含程序集的元数据和注册器
+ /// 异步任务
+ public async FTask OnUnload(AssemblyManifest assemblyManifest)
{
var tcs = FTask.Create(false);
Scene?.ThreadSynchronizationContext.Post(() =>
{
- OnUnLoadInner(assemblyIdentity);
- LoadInner(assemblyIdentity);
+ OnUnLoadInner(assemblyManifest);
tcs.SetResult();
});
await tcs;
}
-
- public async FTask OnUnLoad(long assemblyIdentity)
+
+ ///
+ /// 卸载程序集的内部实现
+ /// 会清理该程序集注册的所有系统
+ ///
+ /// 程序集清单对象,包含程序集的元数据和注册器
+ private void OnUnLoadInner(AssemblyManifest assemblyManifest)
{
- var tcs = FTask.Create(false);
- Scene?.ThreadSynchronizationContext.Post(() =>
- {
- OnUnLoadInner(assemblyIdentity);
- tcs.SetResult();
- });
- await tcs;
- }
-
- private void LoadInner(long assemblyIdentity)
- {
- foreach (var type in AssemblySystem.ForEach(assemblyIdentity, typeof(IEvent)))
- {
- var @event = (IEvent)Activator.CreateInstance(type);
-
- if (@event == null)
- {
- continue;
- }
-
- var eventType = @event.EventType();
- _events.Add(eventType, @event);
- _assemblyEvents.Add(assemblyIdentity, new EventCache(eventType, @event));
- }
-
- foreach (var type in AssemblySystem.ForEach(assemblyIdentity, typeof(IAsyncEvent)))
- {
- var @event = (IAsyncEvent)Activator.CreateInstance(type);
-
- if (@event == null)
- {
- continue;
- }
-
- var eventType = @event.EventType();
- _asyncEvents.Add(eventType, @event);
- _assemblyAsyncEvents.Add(assemblyIdentity, new EventCache(eventType, @event));
- }
- }
-
- private void OnUnLoadInner(long assemblyIdentity)
- {
- if (_assemblyEvents.TryGetValue(assemblyIdentity, out var events))
- {
- foreach (var @event in events)
- {
- _events.RemoveValue(@event.EnventType, (IEvent)@event.Obj);
- }
-
- _assemblyEvents.RemoveByKey(assemblyIdentity);
- }
-
- if (_assemblyAsyncEvents.TryGetValue(assemblyIdentity, out var asyncEvents))
- {
- foreach (var @event in asyncEvents)
- {
- _asyncEvents.RemoveValue(@event.EnventType, (IAsyncEvent)@event.Obj);
- }
-
- _assemblyAsyncEvents.RemoveByKey(assemblyIdentity);
- }
+ assemblyManifest.EventSystemRegistrar.UnRegisterSystems(
+ _events,
+ _asyncEvents,
+ _sphereEvents);
+ _assemblyManifests.Remove(assemblyManifest.AssemblyManifestId);
}
#endregion
@@ -131,13 +110,13 @@ namespace Fantasy.Event
#region Publish
///
- /// 发布一个值类型的事件数据。
+ /// 发布同步事件(struct类型)
///
- /// 事件数据类型(值类型)。
- /// 事件数据实例。
+ /// 事件数据类型(值类型)
+ /// 事件数据
public void Publish(TEventData eventData) where TEventData : struct
{
- if (!_events.TryGetValue(typeof(TEventData), out var list))
+ if (!_events.TryGetValue(typeof(TEventData).TypeHandle, out var list))
{
return;
}
@@ -146,7 +125,7 @@ namespace Fantasy.Event
{
try
{
- @event.Invoke(eventData);
+ ((IEvent)@event).Invoke(eventData);
}
catch (Exception e)
{
@@ -156,14 +135,14 @@ namespace Fantasy.Event
}
///
- /// 发布一个继承自 Entity 的事件数据。
+ /// 发布同步事件(Entity类型)
///
- /// 事件数据类型(继承自 Entity)。
- /// 事件数据实例。
- /// 是否释放事件数据。
+ /// 事件数据类型(Entity类型)
+ /// 事件数据
+ /// 事件处理完成后是否自动销毁Entity
public void Publish(TEventData eventData, bool isDisposed = true) where TEventData : Entity
{
- if (!_events.TryGetValue(typeof(TEventData), out var list))
+ if (!_events.TryGetValue(typeof(TEventData).TypeHandle, out var list))
{
return;
}
@@ -172,7 +151,8 @@ namespace Fantasy.Event
{
try
{
- @event.Invoke(eventData);
+ // 转换为泛型接口,Entity是引用类型但仍避免虚方法调用开销
+ ((IEvent)@event).Invoke(eventData);
}
catch (Exception e)
{
@@ -185,68 +165,72 @@ namespace Fantasy.Event
eventData.Dispose();
}
}
-
- ///
- /// 异步发布一个值类型的事件数据。
- ///
- /// 事件数据类型(值类型)。
- /// 事件数据实例。
- /// 表示异步操作的任务。
- public async FTask PublishAsync(TEventData eventData) where TEventData : struct
- {
- if (!_asyncEvents.TryGetValue(typeof(TEventData), out var list))
- {
- return;
- }
-
- using var tasks = ListPool.Create();
-
- foreach (var @event in list)
- {
- tasks.Add(@event.InvokeAsync(eventData));
- }
-
- await FTask.WaitAll(tasks);
- }
-
- ///
- /// 异步发布一个继承自 Entity 的事件数据。
- ///
- /// 事件数据类型(继承自 Entity)。
- /// 事件数据实例。
- /// 是否释放事件数据。
- /// 表示异步操作的任务。
- public async FTask PublishAsync(TEventData eventData, bool isDisposed = true) where TEventData : Entity
- {
- if (!_asyncEvents.TryGetValue(eventData.GetType(), out var list))
- {
- return;
- }
-
- using var tasks = ListPool.Create();
-
- foreach (var @event in list)
- {
- tasks.Add(@event.InvokeAsync(eventData));
- }
-
- await FTask.WaitAll(tasks);
-
- if (isDisposed)
- {
- eventData.Dispose();
- }
- }
- #endregion
-
- public override void Dispose()
+ ///
+ /// 发布异步事件(struct类型)
+ ///
+ /// 事件数据类型(值类型)
+ /// 事件数据
+ public async FTask PublishAsync(TEventData eventData) where TEventData : struct
{
- _events.Clear();
- _asyncEvents.Clear();
- _assemblyEvents.Clear();
- _assemblyAsyncEvents.Clear();
- base.Dispose();
+ if (!_asyncEvents.TryGetValue(typeof(TEventData).TypeHandle, out var list))
+ {
+ return;
+ }
+
+ using var tasks = ListPool.Create();
+
+ foreach (var @event in list)
+ {
+ try
+ {
+ tasks.Add(((IAsyncEvent)@event).InvokeAsync(eventData));
+ }
+ catch (Exception e)
+ {
+ Log.Error(e);
+ }
+ }
+
+ await FTask.WaitAll(tasks);
}
+
+ ///
+ /// 发布异步事件(Entity类型)
+ ///
+ /// 事件数据类型(Entity类型)
+ /// 事件数据
+ /// 事件处理完成后是否自动销毁Entity
+ public async FTask PublishAsync(TEventData eventData, bool isDisposed = true) where TEventData : Entity
+ {
+ if (!_asyncEvents.TryGetValue(typeof(TEventData).TypeHandle, out var list))
+ {
+ return;
+ }
+
+ using var tasks = ListPool.Create();
+
+ foreach (var @event in list)
+ {
+ try
+ {
+ tasks.Add(((IAsyncEvent)@event).InvokeAsync(eventData));
+ }
+ catch (Exception e)
+ {
+ Log.Error(e);
+ }
+ }
+
+ await FTask.WaitAll(tasks);
+
+ if (isDisposed)
+ {
+ eventData.Dispose();
+ }
+ }
+
+ #endregion
}
-}
\ No newline at end of file
+}
+
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EventComponent/Interface/IEvent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EventComponent/Interface/IEvent.cs
index 5314995..e093db9 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EventComponent/Interface/IEvent.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/EventComponent/Interface/IEvent.cs
@@ -13,35 +13,53 @@ namespace Fantasy.Event
///
///
Type EventType();
- ///
- /// 时间内部使用的入口
- ///
- ///
- void Invoke(object self);
}
-
+
///
- /// 异步事件的接口
+ /// 事件的泛型接口
///
- public interface IAsyncEvent
+ /// 事件数据类型
+ public interface IEvent : IEvent
{
///
- ///
+ /// 事件内部使用的入口
///
- ///
- Type EventType();
+ /// 事件数据
+ void Invoke(T self);
+ }
+
+ ///
+ /// 异步事件的泛型接口
+ ///
+ /// 事件数据类型
+ public interface IAsyncEvent : IEvent
+ {
///
- ///
+ /// 异步事件调用入口
///
- ///
- FTask InvokeAsync(object self);
+ /// 事件数据
+ FTask InvokeAsync(T self);
+ }
+
+ ///
+ /// 领域事件的泛型接口
+ ///
+ /// 事件数据类型
+ public interface ISphereEvent : IEvent
+ {
+ ///
+ /// 领域事件调用入口
+ ///
+ /// 事件数据
+ FTask Invoke(T self);
}
///
/// 事件的抽象类,要使用事件必须要继承这个抽象接口。
+ /// 同时实现泛型和非泛型接口,支持零装箱调用
///
/// 要监听的事件泛型类型
- public abstract class EventSystem : IEvent
+ public abstract class EventSystem : IEvent
{
private readonly Type _selfType = typeof(T);
///
@@ -52,20 +70,22 @@ namespace Fantasy.Event
{
return _selfType;
}
+
///
/// 事件调用的方法,要在这个方法里编写事件发生的逻辑
///
///
protected abstract void Handler(T self);
+
///
- ///
+ /// 泛型调用入口
///
- ///
- public void Invoke(object self)
+ /// 事件数据
+ public void Invoke(T self)
{
try
{
- Handler((T) self);
+ Handler(self);
}
catch (Exception e)
{
@@ -75,9 +95,10 @@ namespace Fantasy.Event
}
///
/// 异步事件的抽象类,要使用事件必须要继承这个抽象接口。
+ /// 同时实现泛型和非泛型接口,支持零装箱调用
///
/// 要监听的事件泛型类型
- public abstract class AsyncEventSystem : IAsyncEvent
+ public abstract class AsyncEventSystem : IAsyncEvent
{
private readonly Type _selfType = typeof(T);
///
@@ -93,15 +114,55 @@ namespace Fantasy.Event
///
///
protected abstract FTask Handler(T self);
+
///
- ///
+ /// 泛型异步调用入口
///
- ///
- public async FTask InvokeAsync(object self)
+ /// 事件数据
+ public async FTask InvokeAsync(T self)
{
try
{
- await Handler((T) self);
+ await Handler(self);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"{_selfType.Name} Error {e}");
+ }
+ }
+ }
+ ///
+ /// 领域事件的抽象类,要使用事件必须要继承这个抽象接口。
+ /// 同时实现泛型和非泛型接口,支持零装箱调用
+ ///
+ /// 要监听的事件泛型类型
+ public abstract class SphereEventSystem : ISphereEvent
+ {
+ private readonly Type _selfType = typeof(T);
+ ///
+ ///
+ ///
+ ///
+ public Type EventType()
+ {
+ return _selfType;
+ }
+
+ ///
+ /// 事件调用的方法,要在这个方法里编写事件发生的逻辑
+ ///
+ ///
+ protected abstract FTask Handler(T self);
+
+ ///
+ /// 泛型调用入口
+ ///
+ /// 事件数据
+ public async FTask Invoke(T self)
+ {
+ try
+ {
+ await Handler(self);
}
catch (Exception e)
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/MessagePoolComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/MessagePoolComponent.cs
index f1ddb23..8227e06 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/MessagePoolComponent.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/MessagePoolComponent.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Fantasy.DataStructure.Collection;
using Fantasy.Entitas;
+using Fantasy.Network.Interface;
using Fantasy.Pool;
using Fantasy.Serialize;
@@ -17,8 +18,8 @@ namespace Fantasy.Entitas
{
private int _poolCount;
private const int MaxCapacity = ushort.MaxValue;
- private readonly OneToManyQueue _poolQueue = new OneToManyQueue();
- private readonly Dictionary> _typeCheckCache = new Dictionary>();
+ private readonly OneToManyQueue _poolQueue = new OneToManyQueue();
+ private readonly Dictionary> _typeCheckCache = new Dictionary>();
///
/// 销毁组件
///
@@ -36,7 +37,7 @@ namespace Fantasy.Entitas
///
public T Rent() where T : AMessage, new()
{
- if (!_poolQueue.TryDequeue(typeof(T), out var queue))
+ if (!_poolQueue.TryDequeue(typeof(T).TypeHandle, out var queue))
{
var instance = new T();
instance.SetScene(Scene);
@@ -58,9 +59,10 @@ namespace Fantasy.Entitas
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AMessage Rent(Type type)
{
- if (!_poolQueue.TryDequeue(type, out var queue))
+ var runtimeTypeHandle = type.TypeHandle;
+ if (!_poolQueue.TryDequeue(runtimeTypeHandle, out var queue))
{
- if (!_typeCheckCache.TryGetValue(type, out var createInstance))
+ if (!_typeCheckCache.TryGetValue(runtimeTypeHandle, out var createInstance))
{
if (!typeof(AMessage).IsAssignableFrom(type))
{
@@ -69,7 +71,7 @@ namespace Fantasy.Entitas
else
{
createInstance = CreateInstance.CreateMessage(type);
- _typeCheckCache[type] = createInstance;
+ _typeCheckCache[runtimeTypeHandle] = createInstance;
}
}
@@ -106,7 +108,7 @@ namespace Fantasy.Entitas
_poolCount++;
obj.SetIsPool(false);
- _poolQueue.Enqueue(obj.GetType(), obj);
+ _poolQueue.Enqueue(obj.GetType().TypeHandle, obj);
}
///
@@ -133,7 +135,7 @@ namespace Fantasy.Entitas
_poolCount++;
obj.SetIsPool(false);
- _poolQueue.Enqueue(typeof(T), obj);
+ _poolQueue.Enqueue(typeof(T).TypeHandle, obj);
}
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SeparateTableComponent/SeparateTableAttribute.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SeparateTableComponent/SeparateTableAttribute.cs
new file mode 100644
index 0000000..3a63d0c
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SeparateTableComponent/SeparateTableAttribute.cs
@@ -0,0 +1,49 @@
+#if FANTASY_NET
+namespace Fantasy.SeparateTable;
+
+///
+/// 分表存储特性,用于标记需要进行数据库分表存储的实体类型。
+/// 当实体标记此特性后,该实体将作为父实体的子组件,并在数据库中使用独立的集合进行存储。
+///
+///
+/// 使用场景:
+/// - 当父实体的某些数据量较大,需要拆分到独立的数据库表中存储时
+/// - 需要优化数据库查询性能,避免单表数据过大时
+/// - Source Generator 会自动生成注册代码,无需手动反射处理
+///
+///
+///
+/// [SeparateTable(typeof(Player), "PlayerInventory")]
+/// public class PlayerInventoryEntity : Entity
+/// {
+/// // 实体字段...
+/// }
+///
+///
+[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
+public class SeparateTableAttribute : Attribute
+{
+ ///
+ /// 获取父实体的类型,指示此实体属于哪个父实体的子集合。
+ /// 通过此属性建立父子实体的逻辑关联关系。
+ ///
+ public readonly Type RootType;
+
+ ///
+ /// 获取在数据库中使用的集合名称(表名)。
+ /// 此实体的数据将单独存储到此命名的集合中。
+ ///
+ public readonly string CollectionName;
+
+ ///
+ /// 初始化 类的新实例,指定父实体类型和数据库集合名称。
+ ///
+ /// 父实体的类型,表示此分表实体从属于哪个父实体。
+ /// 在数据库中存储此实体的集合名称(表名)。
+ public SeparateTableAttribute(Type rootType, string collectionName)
+ {
+ RootType = rootType;
+ CollectionName = collectionName;
+ }
+}
+#endif
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SeparateTableComponent/SeparateTableComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SeparateTableComponent/SeparateTableComponent.cs
new file mode 100644
index 0000000..e1848e1
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SeparateTableComponent/SeparateTableComponent.cs
@@ -0,0 +1,221 @@
+#if FANTASY_NET
+// ReSharper disable SuspiciousTypeConversion.Global
+
+using Fantasy.Assembly;
+using Fantasy.Async;
+using Fantasy.DataStructure.Collection;
+using Fantasy.Entitas;
+using Fantasy.Entitas.Interface;
+using Fantasy.Helper;
+// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS8604 // Possible null reference argument.
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+
+namespace Fantasy.SeparateTable
+{
+ ///
+ /// 分表组件,用于管理实体的数据库分表存储功能。
+ /// 负责注册、加载和保存标记了 的实体数据。
+ ///
+ ///
+ /// 此组件实现了程序集生命周期接口,会在程序集加载/卸载时自动注册/反注册分表信息。
+ /// 通过 Source Generator 生成的注册器自动管理分表实体的元数据,避免运行时反射。
+ ///
+ public sealed class SeparateTableComponent : Entity, IAssemblyLifecycle
+ {
+ ///
+ /// 存储已加载的程序集清单ID集合,用于追踪哪些程序集的分表信息已注册。
+ ///
+ private readonly HashSet _assemblyManifests = new();
+
+ ///
+ /// 分表信息映射表,键为父实体类型,值为该父实体对应的所有分表信息集合。
+ /// 用于快速查询某个实体类型有哪些子实体需要分表存储。
+ ///
+ private readonly OneToManyHashSet _separateTables = new ();
+
+ #region AssemblyManifest
+
+ ///
+ /// 初始化分表组件,将其注册到程序集生命周期管理器中。
+ ///
+ /// 返回初始化后的分表组件实例。
+ internal async FTask Initialize()
+ {
+ await AssemblyLifecycle.Add(this);
+ return this;
+ }
+
+ ///
+ /// 当程序集加载时的回调方法,负责注册该程序集中的所有分表信息。
+ ///
+ /// 加载的程序集清单,包含该程序集的所有元数据。
+ /// 异步任务。
+ ///
+ /// 此方法在线程同步上下文中执行,确保线程安全。
+ /// 如果程序集已被加载过(如热重载场景),会先卸载旧的注册信息再重新注册。
+ ///
+ public async FTask OnLoad(AssemblyManifest assemblyManifest)
+ {
+ var tcs = FTask.Create(false);
+ var assemblyManifestId = assemblyManifest.AssemblyManifestId;
+ Scene?.ThreadSynchronizationContext.Post(() =>
+ {
+ // 如果程序集已加载,先卸载旧的
+ if (_assemblyManifests.Contains(assemblyManifestId))
+ {
+ OnUnLoadInner(assemblyManifest);
+ }
+
+ // 从 Source Generator 生成的注册器中获取分表信息
+ var separateTableInfos = assemblyManifest.SeparateTableRegistrar.Register();
+
+ // 将分表信息按父实体类型进行分组注册
+ foreach (var separateTableInfo in separateTableInfos)
+ {
+ _separateTables.Add(TypeHashCache.GetHashCode(separateTableInfo.RootType), separateTableInfo);
+ }
+
+ _assemblyManifests.Add(assemblyManifestId);
+ tcs.SetResult();
+ });
+ await tcs;
+ }
+
+ ///
+ /// 当程序集卸载时的回调方法,负责反注册该程序集中的所有分表信息。
+ ///
+ /// 卸载的程序集清单。
+ /// 异步任务。
+ ///
+ /// 此方法在线程同步上下文中执行,确保线程安全。
+ ///
+ public FTask OnUnload(AssemblyManifest assemblyManifest)
+ {
+ var task = FTask.Create(false);
+ Scene?.ThreadSynchronizationContext.Post(() =>
+ {
+ OnUnLoadInner(assemblyManifest);
+ task.SetResult();
+ });
+ return task;
+ }
+
+ ///
+ /// 卸载程序集的内部实现,从映射表中移除该程序集的所有分表信息。
+ ///
+ /// 要卸载的程序集清单。
+ private void OnUnLoadInner(AssemblyManifest assemblyManifest)
+ {
+ // 获取该程序集需要反注册的分表信息
+ var separateTableInfos = assemblyManifest.SeparateTableRegistrar.UnRegister();
+
+ // 从映射表中逐个移除
+ foreach (var separateTableInfo in separateTableInfos)
+ {
+ _separateTables.RemoveValue(TypeHashCache.GetHashCode(separateTableInfo.RootType), separateTableInfo);
+ }
+
+ _assemblyManifests.Remove(assemblyManifest.AssemblyManifestId);
+ }
+
+ #endregion
+
+ #region Collections
+
+ ///
+ /// 从数据库加载指定实体的所有分表数据,并自动建立父子关系。
+ ///
+ /// 需要加载分表数据的实体实例。
+ /// 实体的泛型类型,必须继承自 。
+ /// 异步任务。
+ ///
+ /// 此方法会根据实体类型查找其关联的所有分表配置,逐个从数据库中加载对应的分表实体,
+ /// 并通过 AddComponent 方法将这些分表实体作为组件添加到父实体上,建立父子关系。
+ /// 如果实体类型没有配置分表信息,则直接返回不做任何操作。
+ ///
+ ///
+ ///
+ /// var player = await db.Query<Player>(playerId);
+ /// await separateTableComponent.Load(player); // 加载玩家的所有分表数据
+ ///
+ ///
+ public async FTask LoadWithSeparateTables(T entity) where T : Entity
+ {
+ // 检查该实体类型是否配置了分表
+ if (!_separateTables.TryGetValue(entity.TypeHashCode, out var separateTables))
+ {
+ return;
+ }
+
+ var worldDateBase = Scene.World.DataBase;
+
+ // 遍历所有分表配置,逐个加载
+ foreach (var separateTable in separateTables)
+ {
+ // 使用实体ID作为查询条件,从指定的集合中加载分表实体
+ var separateTableEntity = await worldDateBase.QueryNotLock(
+ entity.Id, true, separateTable.TableName);
+
+ if (separateTableEntity == null)
+ {
+ continue;
+ }
+
+ // 将加载的分表实体作为组件添加到父实体上
+ entity.AddComponent(separateTableEntity);
+ }
+ }
+
+ ///
+ /// 将实体及其所有分表组件保存到数据库中。
+ ///
+ /// 需要保存的实体实例。
+ /// 实体的泛型类型,必须继承自 并具有无参构造函数。
+ /// 异步任务。
+ ///
+ /// 此方法会检查实体是否配置了分表信息:
+ /// - 如果没有配置分表,则直接保存实体本身到数据库。
+ /// - 如果配置了分表,会收集实体上所有需要分表存储的组件,统一批量保存到数据库。
+ /// 使用对象池优化列表分配,避免频繁 GC。
+ ///
+ ///
+ ///
+ /// player.Inventory.Items.Add(newItem);
+ /// await separateTableComponent.Save(player); // 保存玩家及分表数据
+ ///
+ ///
+ public async FTask PersistAggregate(T entity) where T : Entity, new()
+ {
+ // 检查该实体类型是否配置了分表
+ if (!_separateTables.TryGetValue(entity.TypeHashCode, out var separateTables))
+ {
+ // 没有分表配置,直接保存实体
+ await entity.Scene.World.DataBase.Save(entity);
+ return;
+ }
+
+ // 使用对象池创建列表,避免 GC
+ using var saveSeparateTables = ListPool.Create(entity);
+
+ // 收集所有需要分表保存的组件
+ foreach (var separateTableInfo in separateTables)
+ {
+ var separateTableEntity = entity.GetComponent(separateTableInfo.EntityType);
+ if (separateTableEntity == null)
+ {
+ continue;
+ }
+ saveSeparateTables.Add(separateTableEntity);
+ }
+
+ // 批量保存实体ID及其所有分表组件
+ await entity.Scene.World.DataBase.Save(entity.Id, saveSeparateTables);
+ }
+
+ #endregion
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SingleCollectionComponent/SingleCollectionComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SingleCollectionComponent/SingleCollectionComponent.cs
deleted file mode 100644
index 5c0969d..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Component/SingleCollectionComponent/SingleCollectionComponent.cs
+++ /dev/null
@@ -1,167 +0,0 @@
-// ReSharper disable SuspiciousTypeConversion.Global
-
-using Fantasy.Assembly;
-using Fantasy.Async;
-using Fantasy.DataStructure.Collection;
-using Fantasy.Entitas;
-using Fantasy.Entitas.Interface;
-using Fantasy.Helper;
-
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
-#pragma warning disable CS8604 // Possible null reference argument.
-#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
-#if FANTASY_NET
-namespace Fantasy.SingleCollection
-{
- ///
- /// 用于处理Entity下的实体进行数据库分表存储的组件
- ///
- public sealed class SingleCollectionComponent : Entity, IAssembly
- {
- private CoroutineLock _coroutineLock;
- private readonly OneToManyHashSet _collection = new OneToManyHashSet();
-
- private readonly OneToManyList _assemblyCollections =
- new OneToManyList();
-
- private sealed class SingleCollectionInfo(Type rootType, string collectionName)
- {
- public readonly Type RootType = rootType;
- public readonly string CollectionName = collectionName;
- }
-
- internal async FTask Initialize()
- {
- var coroutineLockType = HashCodeHelper.ComputeHash64(GetType().FullName);
- _coroutineLock = Scene.CoroutineLockComponent.Create(coroutineLockType);
- await AssemblySystem.Register(this);
- return this;
- }
-
- #region Assembly
-
- public async FTask Load(long assemblyIdentity)
- {
- var tcs = FTask.Create(false);
- Scene?.ThreadSynchronizationContext.Post(() =>
- {
- LoadInner(assemblyIdentity);
- tcs.SetResult();
- });
- await tcs;
- }
-
- public async FTask ReLoad(long assemblyIdentity)
- {
- var tcs = FTask.Create(false);
- Scene?.ThreadSynchronizationContext.Post(() =>
- {
- OnUnLoadInner(assemblyIdentity);
- LoadInner(assemblyIdentity);
- tcs.SetResult();
- });
- await tcs;
- }
-
- public async FTask OnUnLoad(long assemblyIdentity)
- {
- var tcs = FTask.Create(false);
- Scene?.ThreadSynchronizationContext.Post(() =>
- {
- OnUnLoadInner(assemblyIdentity);
- tcs.SetResult();
- });
- await tcs;
- }
-
- private void LoadInner(long assemblyIdentity)
- {
- foreach (var type in AssemblySystem.ForEach(assemblyIdentity, typeof(ISupportedSingleCollection)))
- {
- var customAttributes = type.GetCustomAttributes(typeof(SingleCollectionAttribute), false);
- if (customAttributes.Length == 0)
- {
- Log.Error(
- $"type {type.FullName} Implemented the interface of ISingleCollection, requiring the implementation of SingleCollectionAttribute");
- continue;
- }
-
- var singleCollectionAttribute = (SingleCollectionAttribute)customAttributes[0];
- var rootType = singleCollectionAttribute.RootType;
- var collectionName = singleCollectionAttribute.CollectionName;
- _collection.Add(rootType, collectionName);
- _assemblyCollections.Add(assemblyIdentity, new SingleCollectionInfo(rootType, collectionName));
- }
- }
-
- private void OnUnLoadInner(long assemblyIdentity)
- {
- if (!_assemblyCollections.TryGetValue(assemblyIdentity, out var types))
- {
- return;
- }
-
- foreach (var singleCollectionInfo in types)
- {
- _collection.RemoveValue(singleCollectionInfo.RootType, singleCollectionInfo.CollectionName);
- }
-
- _assemblyCollections.RemoveByKey(assemblyIdentity);
- }
-
- #endregion
-
- #region Collections
-
- ///
- /// 通过数据库获取某一个实体类型下所有的分表数据到当前实体下,并且会自动建立父子关系。
- ///
- /// 实体实例
- /// 实体泛型类型
- public async FTask GetCollections(T entity) where T : Entity, ISingleCollectionRoot
- {
- if (!_collection.TryGetValue(typeof(T), out var collections))
- {
- return;
- }
-
- var worldDateBase = Scene.World.DataBase;
-
- using (await _coroutineLock.Wait(entity.Id))
- {
- foreach (var collectionName in collections)
- {
- var singleCollection = await worldDateBase.QueryNotLock(entity.Id, true, collectionName);
- entity.AddComponent(singleCollection);
- }
- }
- }
-
- ///
- /// 存储当前实体下支持分表的组件到数据中,包括存储实体本身。
- ///
- /// 实体实例
- /// 实体泛型类型
- public async FTask SaveCollections(T entity) where T : Entity, ISingleCollectionRoot
- {
- using var collections = ListPool.Create();
-
- foreach (var treeEntity in entity.ForEachSingleCollection)
- {
- if (treeEntity is not ISupportedSingleCollection)
- {
- continue;
- }
-
- collections.Add(treeEntity);
- }
-
- collections.Add(entity);
- await entity.Scene.World.DataBase.Save(entity.Id, collections);
- }
-
- #endregion
- }
-}
-
-#endif
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Entity.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Entity.cs
index 99faad7..258f59a 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Entity.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Entity.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
+using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using Fantasy.Entitas.Interface;
+using Fantasy.IdFactory;
using Fantasy.Pool;
using MongoDB.Bson.Serialization.Attributes;
using Newtonsoft.Json;
@@ -30,15 +32,7 @@ namespace Fantasy.Entitas
public abstract partial class Entity : IEntity
{
#region Members
-
- ///
- /// 获取一个值,表示实体是否支持对象池。
- ///
- [BsonIgnore]
- [JsonIgnore]
- [ProtoIgnore]
- [IgnoreDataMember]
- private bool _isPool;
+
///
/// 实体的Id
///
@@ -86,6 +80,14 @@ namespace Fantasy.Entitas
[IgnoreDataMember]
[ProtoIgnore]
public Type Type { get; protected set; }
+ ///
+ /// 实体的真实Type的HashCode
+ ///
+ [BsonIgnore]
+ [JsonIgnore]
+ [IgnoreDataMember]
+ [ProtoIgnore]
+ public long TypeHashCode { get; private set; }
#if FANTASY_NET
[BsonElement("t")] [BsonIgnoreIfNull] private EntityList _treeDb;
[BsonElement("m")] [BsonIgnoreIfNull] private EntityList _multiDb;
@@ -98,6 +100,7 @@ namespace Fantasy.Entitas
///
/// 父实体的泛型类型
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public T GetParent() where T : Entity, new()
{
return Parent as T;
@@ -138,10 +141,11 @@ namespace Fantasy.Entitas
{
if (!typeof(Entity).IsAssignableFrom(type))
{
- throw new NotSupportedException($"{type.FullName} Type:{type.FullName} must inherit from Entity");
+ throw new NotSupportedException($"Type:{type.FullName} must inherit from Entity");
}
Entity entity = null;
+ var runtimeTypeHandle = type.TypeHandle;
if (isPool)
{
@@ -149,10 +153,10 @@ namespace Fantasy.Entitas
}
else
{
- if (!scene.TypeInstance.TryGetValue(type, out var createInstance))
+ if (!scene.TypeInstance.TryGetValue(runtimeTypeHandle, out var createInstance))
{
createInstance = CreateInstance.CreateIPool(type);
- scene.TypeInstance[type] = createInstance;
+ scene.TypeInstance[runtimeTypeHandle] = createInstance;
}
entity = (Entity)createInstance();
@@ -160,17 +164,18 @@ namespace Fantasy.Entitas
entity.Scene = scene;
entity.Type = type;
+ entity.TypeHashCode = TypeHashCache.GetHashCode(type);
entity.SetIsPool(isPool);
entity.Id = id;
- entity.RuntimeId = scene.RuntimeIdFactory.Create;
+ entity.RuntimeId = scene.RuntimeIdFactory.Create(isPool);
scene.AddEntity(entity);
if (isRunEvent)
{
scene.EntityComponent.Awake(entity);
- scene.EntityComponent.StartUpdate(entity);
+ scene.EntityComponent.RegisterUpdate(entity);
#if FANTASY_UNITY
- scene.EntityComponent.StartLateUpdate(entity);
+ scene.EntityComponent.RegisterLateUpdate(entity);
#endif
}
@@ -204,17 +209,18 @@ namespace Fantasy.Entitas
var entity = isPool ? scene.EntityPool.Rent() : new T();
entity.Scene = scene;
entity.Type = typeof(T);
+ entity.TypeHashCode = EntityTypeHashCache.HashCode;
entity.SetIsPool(isPool);
entity.Id = id;
- entity.RuntimeId = scene.RuntimeIdFactory.Create;
+ entity.RuntimeId = scene.RuntimeIdFactory.Create(isPool);
scene.AddEntity(entity);
if (isRunEvent)
{
scene.EntityComponent.Awake(entity);
- scene.EntityComponent.StartUpdate(entity);
+ scene.EntityComponent.RegisterUpdate(entity);
#if FANTASY_UNITY
- scene.EntityComponent.StartLateUpdate(entity);
+ scene.EntityComponent.RegisterLateUpdate(entity);
#endif
}
@@ -233,13 +239,13 @@ namespace Fantasy.Entitas
/// 返回添加到实体上组件的实例
public T AddComponent(bool isPool = true) where T : Entity, new()
{
- var id = SupportedMultiEntityChecker.IsSupported ? Scene.EntityIdFactory.Create : Id;
+ var id = EntitySupportedChecker.IsMulti ? Scene.EntityIdFactory.Create : Id;
var entity = Create(Scene, id, isPool, false);
AddComponent(entity);
Scene.EntityComponent.Awake(entity);
- Scene.EntityComponent.StartUpdate(entity);
+ Scene.EntityComponent.RegisterUpdate(entity);
#if FANTASY_UNITY
- Scene.EntityComponent.StartLateUpdate(entity);
+ Scene.EntityComponent.RegisterLateUpdate(entity);
#endif
return entity;
}
@@ -256,9 +262,9 @@ namespace Fantasy.Entitas
var entity = Create(Scene, id, isPool, false);
AddComponent(entity);
Scene.EntityComponent.Awake(entity);
- Scene.EntityComponent.StartUpdate(entity);
+ Scene.EntityComponent.RegisterUpdate(entity);
#if FANTASY_UNITY
- Scene.EntityComponent.StartLateUpdate(entity);
+ Scene.EntityComponent.RegisterLateUpdate(entity);
#endif
return entity;
}
@@ -298,13 +304,7 @@ namespace Fantasy.Entitas
}
else
{
-#if FANTASY_NET
- if (component is ISupportedSingleCollection && component.Id != Id)
- {
- Log.Error($"component type :{type.FullName} for implementing ISupportedSingleCollection, it is required that the Id must be the same as the parent");
- }
-#endif
- var typeHashCode = Scene.EntityComponent.GetHashCode(type);;
+ var typeHashCode = component.TypeHashCode;
if (_tree == null)
{
@@ -337,14 +337,6 @@ namespace Fantasy.Entitas
/// 要添加组件的泛型类型
public void AddComponent(T component) where T : Entity
{
- var type = typeof(T);
-
- if (type == typeof(Entity))
- {
- Log.Error("Cannot add a generic Entity type as a component. Specify a more specific type.");
- return;
- }
-
if (this == component)
{
Log.Error("Cannot add oneself to one's own components");
@@ -353,18 +345,18 @@ namespace Fantasy.Entitas
if (component.IsDisposed)
{
- Log.Error($"component is Disposed {type.FullName}");
+ Log.Error($"component is Disposed {typeof(T).FullName}");
return;
}
component.Parent?.RemoveComponent(component, false);
- if (SupportedMultiEntityChecker.IsSupported)
+ if (EntitySupportedChecker.IsMulti)
{
_multi ??= Scene.EntitySortedDictionaryPool.Rent();
_multi.Add(component.Id, component);
#if FANTASY_NET
- if (SupportedDataBaseChecker.IsSupported)
+ if (EntitySupportedChecker.IsDataBase)
{
_multiDb ??= Scene.EntityListPool.Rent();
_multiDb.Add(component);
@@ -373,13 +365,7 @@ namespace Fantasy.Entitas
}
else
{
-#if FANTASY_NET
- if (SupportedSingleCollectionChecker.IsSupported && component.Id != Id)
- {
- Log.Error($"component type :{type.FullName} for implementing ISupportedSingleCollection, it is required that the Id must be the same as the parent");
- }
-#endif
- var typeHashCode = Scene.EntityComponent.GetHashCode(type);
+ var typeHashCode = component.TypeHashCode;
if (_tree == null)
{
@@ -387,13 +373,13 @@ namespace Fantasy.Entitas
}
else if (_tree.ContainsKey(typeHashCode))
{
- Log.Error($"type:{type.FullName} If you want to add multiple components of the same type, please implement IMultiEntity");
+ Log.Error($"type:{typeof(T).FullName} If you want to add multiple components of the same type, please implement IMultiEntity");
return;
}
_tree.Add(typeHashCode, component);
#if FANTASY_NET
- if (SupportedDataBaseChecker.IsSupported)
+ if (EntitySupportedChecker.IsDataBase)
{
_treeDb ??= Scene.EntityListPool.Rent();
_treeDb.Add(component);
@@ -406,7 +392,7 @@ namespace Fantasy.Entitas
}
///
- /// 添加一个组件到当前实体上
+ /// 添加一个组件到当前实体上
///
/// 组件的类型
/// 是否在对象池创建
@@ -417,9 +403,9 @@ namespace Fantasy.Entitas
var entity = Entity.Create(Scene, type, id, isPool, false);
AddComponent(entity);
Scene.EntityComponent.Awake(entity);
- Scene.EntityComponent.StartUpdate(entity);
+ Scene.EntityComponent.RegisterUpdate(entity);
#if FANTASY_UNITY
- Scene.EntityComponent.StartLateUpdate(entity);
+ Scene.EntityComponent.RegisterLateUpdate(entity);
#endif
return entity;
}
@@ -433,9 +419,15 @@ namespace Fantasy.Entitas
///
///
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasComponent() where T : Entity, new()
{
- return HasComponent(typeof(T));
+ if (_tree == null)
+ {
+ return false;
+ }
+
+ return _tree.ContainsKey(EntityTypeHashCache.HashCode);
}
///
@@ -443,14 +435,15 @@ namespace Fantasy.Entitas
///
///
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasComponent(Type type)
{
if (_tree == null)
{
return false;
}
-
- return _tree.ContainsKey(Scene.EntityComponent.GetHashCode(type));
+
+ return _tree.ContainsKey(TypeHashCache.GetHashCode(type));
}
///
@@ -459,6 +452,7 @@ namespace Fantasy.Entitas
///
///
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasComponent(long id) where T : Entity, ISupportedMultiEntity, new()
{
if (_multi == null)
@@ -474,10 +468,11 @@ namespace Fantasy.Entitas
#region GetComponent
///
- /// 当前实体上查找一个字实体
+ /// 当前实体上查找一个子实体
///
/// 要查找实体泛型类型
/// 查找的实体实例
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public T GetComponent() where T : Entity, new()
{
if (_tree == null)
@@ -485,15 +480,15 @@ namespace Fantasy.Entitas
return null;
}
- var typeHashCode = Scene.EntityComponent.GetHashCode(typeof(T));
- return _tree.TryGetValue(typeHashCode, out var component) ? (T)component : null;
+ return _tree.TryGetValue(EntityTypeHashCache.HashCode, out var component) ? (T)component : null;
}
///
- /// 当前实体上查找一个字实体
+ /// 当前实体上查找一个子实体
///
/// 要查找实体类型
/// 查找的实体实例
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Entity GetComponent(Type type)
{
if (_tree == null)
@@ -501,28 +496,28 @@ namespace Fantasy.Entitas
return null;
}
- var typeHashCode = Scene.EntityComponent.GetHashCode(type);
- return _tree.TryGetValue(typeHashCode, out var component) ? component : null;
+ return _tree.GetValueOrDefault(TypeHashCache.GetHashCode(type));
}
///
- /// 当前实体上查找一个字实体
+ /// 当前实体上查找一个子实体
///
/// 要查找实体的Id
/// 要查找实体泛型类型
/// 查找的实体实例
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public T GetComponent(long id) where T : Entity, ISupportedMultiEntity, new()
{
if (_multi == null)
{
- return default;
+ return null;
}
- return _multi.TryGetValue(id, out var entity) ? (T)entity : default;
+ return _multi.TryGetValue(id, out var entity) ? (T)entity : null;
}
///
- /// 当前实体上查找一个字实体,如果没有就创建一个新的并添加到当前实体上
+ /// 当前实体上查找一个子实体,如果没有就创建一个新的并添加到当前实体上
///
/// 是否从对象池创建
/// 要查找或添加实体泛型类型
@@ -544,7 +539,7 @@ namespace Fantasy.Entitas
///
public void RemoveComponent(bool isDispose = true) where T : Entity, new()
{
- if (SupportedMultiEntityChecker.IsSupported)
+ if (EntitySupportedChecker.IsMulti)
{
throw new NotSupportedException($"{typeof(T).FullName} message:Cannot delete components that implement the ISupportedMultiEntity interface");
}
@@ -554,14 +549,13 @@ namespace Fantasy.Entitas
return;
}
- var type = typeof(T);
- var typeHashCode = Scene.EntityComponent.GetHashCode(type);
+ var typeHashCode = EntityTypeHashCache.HashCode;
if (!_tree.TryGetValue(typeHashCode, out var component))
{
return;
}
#if FANTASY_NET
- if (_treeDb != null && SupportedDataBaseChecker.IsSupported)
+ if (_treeDb != null && EntitySupportedChecker.IsDataBase)
{
_treeDb.Remove(component);
@@ -604,7 +598,7 @@ namespace Fantasy.Entitas
return;
}
#if FANTASY_NET
- if (SupportedDataBaseChecker.IsSupported)
+ if (_multiDb != null && EntitySupportedChecker.IsDataBase)
{
_multiDb.Remove(component);
if (_multiDb.Count == 0)
@@ -668,7 +662,7 @@ namespace Fantasy.Entitas
}
else if (_tree != null)
{
- var typeHashCode = Scene.EntityComponent.GetHashCode(component.Type);
+ var typeHashCode = component.TypeHashCode;
if (!_tree.ContainsKey(typeHashCode))
{
return;
@@ -712,14 +706,8 @@ namespace Fantasy.Entitas
{
return;
}
-
- if (typeof(T) == typeof(Entity))
- {
- Log.Error("Cannot remove a generic Entity type as a component. Specify a more specific type.");
- return;
- }
-
- if (SupportedMultiEntityChecker.IsSupported)
+
+ if (EntitySupportedChecker.IsMulti)
{
if (_multi != null)
{
@@ -728,7 +716,7 @@ namespace Fantasy.Entitas
return;
}
#if FANTASY_NET
- if (SupportedDataBaseChecker.IsSupported)
+ if (EntitySupportedChecker.IsDataBase)
{
_multiDb.Remove(component);
if (_multiDb.Count == 0)
@@ -748,13 +736,13 @@ namespace Fantasy.Entitas
}
else if (_tree != null)
{
- var typeHashCode = Scene.EntityComponent.GetHashCode(typeof(T));
+ var typeHashCode = EntityTypeHashCache.HashCode;
if (!_tree.ContainsKey(typeHashCode))
{
return;
}
#if FANTASY_NET
- if (_treeDb != null && SupportedDataBaseChecker.IsSupported)
+ if (_treeDb != null && EntitySupportedChecker.IsDataBase)
{
_treeDb.Remove(component);
@@ -801,7 +789,7 @@ namespace Fantasy.Entitas
{
Scene = scene;
Type ??= GetType();
- RuntimeId = Scene.RuntimeIdFactory.Create;
+ RuntimeId = Scene.RuntimeIdFactory.Create(false);
if (resetId)
{
Id = RuntimeId;
@@ -814,8 +802,7 @@ namespace Fantasy.Entitas
{
entity.Parent = this;
entity.Type = entity.GetType();
- var typeHashCode = Scene.EntityComponent.GetHashCode(entity.Type);
- _tree.Add(typeHashCode, entity);
+ _tree.Add(TypeHashCache.GetHashCode(entity.Type), entity);
entity.Deserialize(scene, resetId);
}
}
@@ -848,66 +835,7 @@ namespace Fantasy.Entitas
#endregion
#region ForEach
-#if FANTASY_NET
- ///
- /// 查询当前实体下支持数据库分表存储实体
- ///
- [BsonIgnore]
- [JsonIgnore]
- [IgnoreDataMember]
- [ProtoIgnore]
- public IEnumerable ForEachSingleCollection
- {
- get
- {
- foreach (var (_, treeEntity) in _tree)
- {
- if (treeEntity is not ISupportedSingleCollection)
- {
- continue;
- }
-
- yield return treeEntity;
- }
- }
- }
- ///
- /// 查询当前实体下支持传送实体
- ///
- [BsonIgnore]
- [JsonIgnore]
- [IgnoreDataMember]
- [ProtoIgnore]
- public IEnumerable ForEachTransfer
- {
- get
- {
- if (_tree != null)
- {
- foreach (var (_, treeEntity) in _tree)
- {
- if (treeEntity is ISupportedTransfer)
- {
- yield return treeEntity;
- }
- }
- }
-
- if (_multiDb != null)
- {
- foreach (var treeEntity in _multiDb)
- {
- if (treeEntity is not ISupportedTransfer)
- {
- continue;
- }
-
- yield return treeEntity;
- }
- }
- }
- }
-#endif
+
///
/// 查询当前实体下的实现了ISupportedMultiEntity接口的实体
///
@@ -996,11 +924,6 @@ namespace Fantasy.Entitas
#if FANTASY_NET
if (_treeDb != null)
{
- foreach (var entity in _treeDb)
- {
- entity.Dispose();
- }
-
_treeDb.Clear();
scene.EntityListPool.Return(_treeDb);
_treeDb = null;
@@ -1008,11 +931,6 @@ namespace Fantasy.Entitas
if (_multiDb != null)
{
- foreach (var entity in _multiDb)
- {
- entity.Dispose();
- }
-
_multiDb.Clear();
scene.EntityListPool.Return(_multiDb);
_multiDb = null;
@@ -1030,12 +948,7 @@ namespace Fantasy.Entitas
Scene = null;
Parent = null;
scene.RemoveEntity(runTimeId);
-
- if (IsPool())
- {
- scene.EntityPool.Return(Type, this);
- }
-
+ scene.EntityPool.Return(Type, this);
Type = null;
}
@@ -1047,20 +960,27 @@ namespace Fantasy.Entitas
/// 获取一个值,该值指示当前实例是否为对象池中的实例。
///
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsPool()
{
- return _isPool;
+ return IdFactoryHelper.RuntimeIdTool.GetIsPool(RuntimeId);
}
///
/// 设置一个值,该值指示当前实例是否为对象池中的实例。
///
///
- public void SetIsPool(bool isPool)
- {
- _isPool = isPool;
- }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void SetIsPool(bool isPool) { }
#endregion
}
+
+ ///
+ /// Entity的泛型抽象类,如果使用泛型Entity必须继承这个接口才可以使用
+ ///
+ ///
+ public abstract partial class Entity : Entity
+ {
+ }
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/EntityReference.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/EntityReference.cs
index dd1a3fd..cc45713 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/EntityReference.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/EntityReference.cs
@@ -26,6 +26,11 @@ namespace Fantasy.Entitas
_runTimeId = t.RuntimeId;
}
+ ///
+ /// 获取实体引用
+ ///
+ public T Value => _entity?.RuntimeId != _runTimeId ? null : _entity;
+
///
/// 将一个实体转换为EntityReference
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/EntityInterface.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/EntityInterface.cs
new file mode 100644
index 0000000..daf58c6
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/EntityInterface.cs
@@ -0,0 +1,46 @@
+using System;
+
+namespace Fantasy.Entitas.Interface
+{
+ ///
+ /// 支持再一个组件里添加多个同类型组件
+ ///
+ public interface ISupportedMultiEntity : IDisposable
+ {
+ }
+#if FANTASY_NET
+ ///
+ /// Entity支持数据库
+ ///
+// ReSharper disable once InconsistentNaming
+ public interface ISupportedDataBase
+ {
+ }
+
+ // Entity支持分表存储、保存到数据库的时候不会跟随父组件保存在一个表里、会单独保存在一个表里
+ // 需要配合SeparateTableAttribute一起使用、如在Entity类头部定义SeparateTableAttribute(typeOf(Unit), "UnitBag")
+ // SeparateTableAttribute用来定义这个Entity是属于哪个Entity的子集以及表名
+ ///
+ /// 定义实体支持分表存储的接口。当实体需要单独存储在一个数据库表中,并且在保存到数据库时不会与父实体一起保存在同一个表中时,应实现此接口。
+ ///
+ public interface ISupportedSeparateTable
+ {
+ }
+
+ ///
+ /// Entity支持传送
+ ///
+ public interface ISupportedTransfer
+ {
+ }
+
+ // ///
+ // /// Entity保存到数据库的时候会根据子组件设置分表存储特性分表存储在不同的数据库表中
+ // ///
+ // public interface ISeparateTableRoot
+ // {
+ // }
+
+
+#endif
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/EntitySupportedChecker.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/EntitySupportedChecker.cs
new file mode 100644
index 0000000..0fab3f9
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/EntitySupportedChecker.cs
@@ -0,0 +1,58 @@
+namespace Fantasy.Entitas.Interface
+{
+ ///
+ /// 实体接口支持性的编译时检查器。
+ ///
+ /// 要检查的实体类型,必须继承自
+ ///
+ /// 性能优势:
+ ///
+ /// - 静态字段在每个具体类型实例化时仅初始化一次
+ /// - JIT编译器会将静态布尔值内联为常量,实现分支消除优化
+ /// - 避免重复的运行时类型检查开销
+ /// - 多个相关检查集中在同一个静态类,提高CPU缓存局部性
+ ///
+ ///
+ public static class EntitySupportedChecker where T : Entity
+ {
+ ///
+ /// 获取实体类型是否实现了 接口。
+ /// 实现该接口的实体支持在父实体中添加多个同类型的组件实例。
+ ///
+ ///
+ /// 如果实体类型实现了 接口,则为 true;否则为 false。
+ ///
+ public static bool IsMulti { get; }
+#if FANTASY_NET
+ ///
+ /// 获取实体类型是否实现了 接口。
+ /// 实现该接口的实体支持数据库持久化存储。
+ ///
+ ///
+ /// 如果实体类型实现了 接口,则为 true;否则为 false。
+ ///
+ public static bool IsDataBase { get; }
+
+ ///
+ /// 获取实体类型是否实现了 接口。
+ /// 实现该接口的实体支持跨进程传输(如服务器间传送)。
+ ///
+ ///
+ /// 如果实体类型实现了 接口,则为 true;否则为 false。
+ ///
+ public static bool IsTransfer { get; }
+#endif
+ ///
+ /// 静态构造函数,在首次访问该泛型类型时执行一次,缓存所有接口检查结果。
+ ///
+ static EntitySupportedChecker()
+ {
+ var type = typeof(T);
+ IsMulti = typeof(ISupportedMultiEntity).IsAssignableFrom(type);
+#if FANTASY_NET
+ IsDataBase = typeof(ISupportedDataBase).IsAssignableFrom(type);
+ IsTransfer = typeof(ISupportedTransfer).IsAssignableFrom(type);
+#endif
+ }
+ }
+}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISingleCollectionRoot.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISingleCollectionRoot.cs
deleted file mode 100644
index 84de7a4..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISingleCollectionRoot.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
-namespace Fantasy.Entitas.Interface
-{
- ///
- /// Entity保存到数据库的时候会根据子组件设置分离存储特性分表存储在不同的集合表中
- ///
- public interface ISingleCollectionRoot { }
- public static class SingleCollectionRootChecker where T : Entity
- {
- public static bool IsSupported { get; }
-
- static SingleCollectionRootChecker()
- {
- IsSupported = typeof(ISingleCollectionRoot).IsAssignableFrom(typeof(T));
- }
- }
-}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedDataBase.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedDataBase.cs
deleted file mode 100644
index f505241..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedDataBase.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
-namespace Fantasy.Entitas.Interface
-{
- ///
- /// Entity支持数据库
- ///
- // ReSharper disable once InconsistentNaming
- public interface ISupportedDataBase { }
-
- public static class SupportedDataBaseChecker where T : Entity
- {
- public static bool IsSupported { get; }
-
- static SupportedDataBaseChecker()
- {
- IsSupported = typeof(ISupportedDataBase).IsAssignableFrom(typeof(T));
- }
- }
-}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedMultiEntity.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedMultiEntity.cs
deleted file mode 100644
index ee6aeb7..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedMultiEntity.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
-
-namespace Fantasy.Entitas.Interface
-{
- ///
- /// 支持再一个组件里添加多个同类型组件
- ///
- public interface ISupportedMultiEntity : IDisposable { }
-
- public static class SupportedMultiEntityChecker where T : Entity
- {
- public static bool IsSupported { get; }
-
- static SupportedMultiEntityChecker()
- {
- IsSupported = typeof(ISupportedMultiEntity).IsAssignableFrom(typeof(T));
- }
- }
-}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedSingleCollection.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedSingleCollection.cs
deleted file mode 100644
index 302e697..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedSingleCollection.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
-namespace Fantasy.Entitas.Interface
-{
- // Entity是单一集合、保存到数据库的时候不会跟随父组件保存在一个集合里、会单独保存在一个集合里
- // 需要配合SingleCollectionAttribute一起使用、如在Entity类头部定义SingleCollectionAttribute(typeOf(Unit))
- // SingleCollectionAttribute用来定义这个Entity是属于哪个Entity的子集
- ///
- /// 定义实体支持单一集合存储的接口。当实体需要单独存储在一个集合中,并且在保存到数据库时不会与父组件一起保存在同一个集合中时,应实现此接口。
- ///
- public interface ISupportedSingleCollection { }
- public static class SupportedSingleCollectionChecker where T : Entity
- {
- public static bool IsSupported { get; }
-
- static SupportedSingleCollectionChecker()
- {
- IsSupported = typeof(ISupportedSingleCollection).IsAssignableFrom(typeof(T));
- }
- }
- ///
- /// 表示用于指定实体的单一集合存储属性。此属性用于配合 接口使用,
- /// 用于定义实体属于哪个父实体的子集合,以及在数据库中使用的集合名称。
- ///
- [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
- public class SingleCollectionAttribute : Attribute
- {
- ///
- /// 获取父实体的类型,指示此实体是属于哪个父实体的子集合。
- ///
- public readonly Type RootType;
- ///
- /// 获取在数据库中使用的集合名称。
- ///
- public readonly string CollectionName;
- ///
- /// 初始化 类的新实例,指定父实体类型和集合名称。
- ///
- /// 父实体的类型。
- /// 在数据库中使用的集合名称。
- public SingleCollectionAttribute(Type rootType, string collectionName)
- {
- RootType = rootType;
- CollectionName = collectionName;
- }
- }
-}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedTransfer.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedTransfer.cs
deleted file mode 100644
index a3ae4a9..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/ISupportedTransfer.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
-#if FANTASY_NET
-namespace Fantasy.Entitas.Interface
-{
- ///
- /// Entity支持传送
- ///
- public interface ISupportedTransfer { }
- public static class SupportedTransferChecker where T : Entity
- {
- public static bool IsSupported { get; }
-
- static SupportedTransferChecker()
- {
- IsSupported = typeof(ISupportedTransfer).IsAssignableFrom(typeof(T));
- }
- }
-}
-#endif
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/TypeHashCache.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/TypeHashCache.cs
new file mode 100644
index 0000000..bf94597
--- /dev/null
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/Supported/TypeHashCache.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using Fantasy.Helper;
+#pragma warning disable CS8604 // Possible null reference argument.
+
+namespace Fantasy.Entitas.Interface
+{
+ ///
+ /// 实体类型哈希码缓存器。
+ /// 提供两种缓存机制:
+ /// 1. 泛型静态字段缓存(用于泛型方法,零开销)
+ /// 2. 全局字典缓存(用于非泛型方法,运行时查找)
+ ///
+ public static class TypeHashCache
+ {
+ ///
+ /// 全局类型哈希码缓存字典,用于非泛型方法的运行时查找。
+ /// 使用 ConcurrentDictionary 保证线程安全。
+ ///
+ private static readonly ConcurrentDictionary RuntimeCache = new();
+
+ ///
+ /// 获取指定实体类型的哈希码(运行时查找)。
+ /// 首次访问时计算并缓存,后续访问直接返回缓存值。
+ ///
+ /// 实体类型
+ /// 实体类型的哈希码
+ ///
+ /// 使用场景:非泛型方法中使用,如 GetComponent(Type type)
+ /// 性能:首次访问需要计算并插入字典,后续访问为 O(1) 字典查找
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static long GetHashCode(Type type)
+ {
+ return RuntimeCache.GetOrAdd(type.TypeHandle,
+ static (_, fullName) => HashCodeHelper.ComputeHash64(fullName),
+ type.FullName);
+ }
+
+ ///
+ /// 预热缓存,批量计算并缓存一组类型的哈希码。
+ ///
+ /// 要预热的类型集合
+ ///
+ /// 建议在程序初始化时调用,避免运行时首次查找的计算开销。
+ ///
+ public static void Warmup(IEnumerable types)
+ {
+ foreach (var type in types)
+ {
+ if (typeof(Entity).IsAssignableFrom(type))
+ {
+ GetHashCode(type);
+ }
+ }
+ }
+
+ ///
+ /// 清除所有缓存(仅用于热重载场景)。
+ ///
+ internal static void Clear()
+ {
+ RuntimeCache.Clear();
+ }
+ }
+
+ ///
+ /// 实体类型哈希码泛型缓存器。
+ /// 通过泛型静态字段缓存每个实体类型的哈希码,实现零开销的类型哈希码访问。
+ ///
+ /// 要缓存哈希码的实体类型,必须继承自
+ ///
+ /// 性能优势:
+ ///
+ /// - 每个类型的哈希码只计算一次,后续访问直接返回缓存值
+ /// - JIT编译器会将静态字段访问内联为常量
+ /// - 无需字典查找,性能远超运行时缓存
+ /// - 适合在泛型方法中使用,如 GetComponent<T>()
+ ///
+ ///
+ internal static class EntityTypeHashCache where T : Entity
+ {
+ ///
+ /// 获取实体类型 的哈希码。
+ /// 该值在首次访问时计算并缓存,后续访问直接返回缓存值。
+ ///
+ ///
+ /// 实体类型的哈希码,用于在 Entity 的 _tree 字典中快速查找组件。
+ ///
+ public static long HashCode { get; }
+
+ static EntityTypeHashCache()
+ {
+ // 直接调用非泛型版本,复用计算逻辑并共享缓存
+ HashCode = TypeHashCache.GetHashCode(typeof(T));
+ }
+ }
+}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IAwakeSystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IAwakeSystem.cs
index f651701..76897b0 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IAwakeSystem.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IAwakeSystem.cs
@@ -3,7 +3,10 @@ using Fantasy.Async;
namespace Fantasy.Entitas.Interface
{
- internal interface IAwakeSystem : IEntitiesSystem { }
+ ///
+ /// 实体的Awake事件的接口
+ ///
+ public interface IAwakeSystem : IEntitySystem { }
///
/// 实体的Awake事件的抽象接口
///
@@ -14,7 +17,7 @@ namespace Fantasy.Entitas.Interface
/// 实体的类型
///
///
- public Type EntitiesType() => typeof(T);
+ public Type EntityType() => typeof(T);
///
/// 事件的抽象方法,需要自己实现这个方法
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ICustomEntitiesSystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ICustomEntitySystem.cs
similarity index 89%
rename from Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ICustomEntitiesSystem.cs
rename to Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ICustomEntitySystem.cs
index da42e58..d1a2979 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ICustomEntitiesSystem.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ICustomEntitySystem.cs
@@ -7,7 +7,7 @@ namespace Fantasy.Entitas.Interface
/// 如果需要自定义组件事件系统,请继承此接口。
/// 这个接口内部使用。不对外开放。
///
- internal interface ICustomEntitiesSystem
+ internal interface ICustomEntitySystem
{
///
/// 事件类型
@@ -18,7 +18,7 @@ namespace Fantasy.Entitas.Interface
/// 实体的类型
///
///
- Type EntitiesType();
+ Type EntityType();
///
/// 框架内部调用的触发事件方法
///
@@ -31,7 +31,7 @@ namespace Fantasy.Entitas.Interface
/// 如果需要自定义组件事件系统,请继承此抽象类。
///
///
- public abstract class CustomSystem : ICustomEntitiesSystem where T : Entity
+ public abstract class CustomSystem : ICustomEntitySystem where T : Entity
{
///
/// 这个1表示是一个自定义事件类型,执行这个事件是时候需要用到这个1.
@@ -46,7 +46,7 @@ namespace Fantasy.Entitas.Interface
/// 实体的类型
///
///
- public abstract Type EntitiesType();
+ public abstract Type EntityType();
///
/// 框架内部调用的触发Awake的方法。
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IDeserializeSystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IDeserializeSystem.cs
index 9c38ab6..cbadcef 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IDeserializeSystem.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IDeserializeSystem.cs
@@ -3,7 +3,10 @@ using Fantasy.Async;
namespace Fantasy.Entitas.Interface
{
- internal interface IDeserializeSystem : IEntitiesSystem { }
+ ///
+ /// 实体的反序列化事件的接口
+ ///
+ public interface IDeserializeSystem : IEntitySystem { }
///
/// 实体的反序列化事件的抽象接口
///
@@ -14,7 +17,7 @@ namespace Fantasy.Entitas.Interface
/// 实体的类型
///
///
- public Type EntitiesType() => typeof(T);
+ public Type EntityType() => typeof(T);
///
/// 事件的抽象方法,需要自己实现这个方法
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IDestroySystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IDestroySystem.cs
index 531ebbe..9e01410 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IDestroySystem.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IDestroySystem.cs
@@ -3,7 +3,10 @@ using Fantasy.Async;
namespace Fantasy.Entitas.Interface
{
- internal interface IDestroySystem : IEntitiesSystem { }
+ ///
+ /// 实体销毁事件的接口
+ ///
+ public interface IDestroySystem : IEntitySystem { }
///
/// 实体销毁事件的抽象接口
///
@@ -14,7 +17,7 @@ namespace Fantasy.Entitas.Interface
/// 实体的类型
///
///
- public Type EntitiesType() => typeof(T);
+ public Type EntityType() => typeof(T);
///
/// 事件的抽象方法,需要自己实现这个方法
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IEntitiesSystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IEntitiesSystem.cs
deleted file mode 100644
index 555d21a..0000000
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IEntitiesSystem.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-using Fantasy.Async;
-
-namespace Fantasy.Entitas.Interface
-{
- ///
- /// ECS事件系统的核心接口,任何事件都是要继承这个接口
- ///
- public interface IEntitiesSystem
- {
- ///
- /// 实体的类型
- ///
- ///
- Type EntitiesType();
- ///
- /// 框架内部调用的触发事件方法
- ///
- ///
- void Invoke(Entity entity);
- }
-}
\ No newline at end of file
diff --git a/Fantasy/Fantays.Console/Runtime/Core/Entitas/Interface/System/IEntitiesSystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IEntitySystem.cs
similarity index 88%
rename from Fantasy/Fantays.Console/Runtime/Core/Entitas/Interface/System/IEntitiesSystem.cs
rename to Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IEntitySystem.cs
index 555d21a..689fda7 100644
--- a/Fantasy/Fantays.Console/Runtime/Core/Entitas/Interface/System/IEntitiesSystem.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IEntitySystem.cs
@@ -6,13 +6,13 @@ namespace Fantasy.Entitas.Interface
///
/// ECS事件系统的核心接口,任何事件都是要继承这个接口
///
- public interface IEntitiesSystem
+ public interface IEntitySystem
{
///
/// 实体的类型
///
///
- Type EntitiesType();
+ Type EntityType();
///
/// 框架内部调用的触发事件方法
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ILateUpdateSystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ILateUpdateSystem.cs
index 34b5f80..eb39cb0 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ILateUpdateSystem.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/ILateUpdateSystem.cs
@@ -3,7 +3,7 @@ using System;
namespace Fantasy.Entitas.Interface
{
- internal interface ILateUpdateSystem : IEntitiesSystem { }
+ public interface ILateUpdateSystem : IEntitySystem { }
///
/// 实体的LateUpdate事件的抽象接口
@@ -15,7 +15,7 @@ namespace Fantasy.Entitas.Interface
/// 实体的类型
///
///
- public Type EntitiesType() => typeof(T);
+ public Type EntityType() => typeof(T);
///
/// 事件的抽象方法,需要自己实现这个方法
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IUpdateSystem.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IUpdateSystem.cs
index 4b34ac8..cd61cb0 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IUpdateSystem.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Entitas/Interface/System/IUpdateSystem.cs
@@ -2,7 +2,10 @@ using System;
namespace Fantasy.Entitas.Interface
{
- internal interface IUpdateSystem : IEntitiesSystem { }
+ ///
+ /// Update事件的接口
+ ///
+ public interface IUpdateSystem : IEntitySystem { }
///
/// Update事件的抽象接口
///
@@ -13,7 +16,7 @@ namespace Fantasy.Entitas.Interface
/// 实体的类型
///
///
- public Type EntitiesType() => typeof(T);
+ public Type EntityType() => typeof(T);
///
/// 事件的抽象方法,需要自己实现这个方法
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Helper/TimeHelper.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Helper/TimeHelper.cs
index b0eb60a..ae4cbe5 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Helper/TimeHelper.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Helper/TimeHelper.cs
@@ -47,7 +47,7 @@ namespace Fantasy.Helper
///
/// 根据时间获取时间戳
///
- public static long Transition(DateTime dateTime)
+ public static long Transition(this DateTime dateTime)
{
return (dateTime.ToUniversalTime().Ticks - Epoch) / 10000;
}
@@ -55,7 +55,7 @@ namespace Fantasy.Helper
///
/// 根据时间获取 时间戳
///
- public static long TransitionToSeconds(DateTime dateTime)
+ public static long TransitionToSeconds(this DateTime dateTime)
{
return (dateTime.ToUniversalTime().Ticks - Epoch) / 10000000;
}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Default/EntityIdStruct.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Default/EntityIdStruct.cs
index ef30b18..cee27b4 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Default/EntityIdStruct.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Default/EntityIdStruct.cs
@@ -114,6 +114,18 @@ namespace Fantasy.IdFactory
public sealed class EntityIdFactoryTool : IIdFactoryTool
{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool GetIsPool(ref long entityId)
+ {
+ throw new NotImplementedException();
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool GetIsPool(long runtimeId)
+ {
+ throw new NotImplementedException();
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetTime(ref long entityId)
{
@@ -121,6 +133,12 @@ namespace Fantasy.IdFactory
return (uint)(result & EntityIdStruct.MaskTime);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetTime(long entityId)
+ {
+ return GetTime(ref entityId);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetSceneId(ref long entityId)
{
@@ -128,9 +146,20 @@ namespace Fantasy.IdFactory
return (uint)(result & EntityIdStruct.MaskSceneId);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetSceneId(long entityId)
+ {
+ return GetSceneId(ref entityId);
+ }
+
public byte GetWorldId(ref long entityId)
{
throw new NotImplementedException();
}
+
+ public byte GetWorldId(long entityId)
+ {
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Default/RuntimeIdStruct.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Default/RuntimeIdStruct.cs
index a5d5e10..f49f42e 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Default/RuntimeIdStruct.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Default/RuntimeIdStruct.cs
@@ -12,27 +12,30 @@ namespace Fantasy.IdFactory
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RuntimeIdStruct
{
- // RuntimeId:23 + 8 + 8 + 25 = 64
- // +-------------------+-----------------------------+--------------------------------------+
- // | time(23) 最大60天 | SceneId(16) 最多65535个Scene | sequence(25) 每秒每个进程能生产33554431个
- // +-------------------+-----------------------------+--------------------------------------+
+ // RuntimeId: IsPool(1) + time(23) + SceneId(16) + sequence(24) = 64 bits
+ // +------------------+-------------------+-----------------------------+--------------------------------------+
+ // | IsPool(1) 对象池 | time(23) 最大60天 | SceneId(16) 最多65535个Scene | sequence(24) 每秒每个进程能生产16777215个
+ // +------------------+-------------------+-----------------------------+--------------------------------------+
public uint Time { get; private set; }
public uint SceneId { get; private set; }
public uint Sequence { get; private set; }
+ public bool IsPool { get; private set; }
+
+ public const uint MaskSequence = 0xFFFFFF; // 24位
+ public const uint MaskSceneId = 0xFFFF; // 16位
+ public const uint MaskTime = 0x7FFFFF; // 23位 (最高位留给 IsPool)
- public const uint MaskSequence = 0x1FFFFFF;
- public const uint MaskSceneId = 0xFFFF;
- public const uint MaskTime = 0x7FFFFF;
-
///
/// RuntimeIdStruct(如果超过下面参数的设定该ID会失效)。
///
+ ///
/// time不能超过8388607
/// sceneId不能超过65535
- /// sequence不能超过33554431
- public RuntimeIdStruct(uint time, uint sceneId, uint sequence)
+ /// sequence不能超过16777215
+ public RuntimeIdStruct(bool isPool, uint time, uint sceneId, uint sequence)
{
// 因为都是在配置表里拿到参数、所以这个不做边界判定、能节省一点点性能。
+ IsPool = isPool;
Time = time;
SceneId = sceneId;
Sequence = sequence;
@@ -40,9 +43,10 @@ namespace Fantasy.IdFactory
public static implicit operator long(RuntimeIdStruct runtimeIdStruct)
{
- ulong result = runtimeIdStruct.Sequence;
- result |= (ulong)runtimeIdStruct.SceneId << 25;
- result |= (ulong)runtimeIdStruct.Time << 41;
+ ulong result = runtimeIdStruct.Sequence; // 低24位: sequence
+ result |= (ulong)runtimeIdStruct.SceneId << 24; // 第24-39位: sceneId
+ result |= (ulong)runtimeIdStruct.Time << 40; // 第40-62位: time
+ result |= (runtimeIdStruct.IsPool ? 1UL : 0UL) << 63; // 最高位63: isPool
return (long)result;
}
@@ -51,12 +55,11 @@ namespace Fantasy.IdFactory
var result = (ulong)runtimeId;
var runtimeIdStruct = new RuntimeIdStruct
{
- Sequence = (uint)(result & MaskSequence)
+ Sequence = (uint)(result & MaskSequence), // 低24位: sequence
+ SceneId = (uint)((result >> 24) & MaskSceneId), // 第24-39位: sceneId
+ Time = (uint)((result >> 40) & MaskTime), // 第40-62位: time
+ IsPool = ((result >> 63) & 1) == 1 // 最高位63: isPool
};
- result >>= 25;
- runtimeIdStruct.SceneId = (byte)(result & MaskSceneId);
- result >>= 16;
- runtimeIdStruct.Time = (uint)(result & MaskTime);
return runtimeIdStruct;
}
}
@@ -91,47 +94,102 @@ namespace Fantasy.IdFactory
}
}
- public long Create
+ public long Create(bool isPool)
{
- get
+ var time = (uint)((TimeHelper.Now - _epochNow) / 1000);
+
+ if (time > _lastTime)
{
- 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);
+ _lastTime = time;
+ _lastSequence = 0;
}
+ else if (++_lastSequence > RuntimeIdStruct.MaskSequence - 1)
+ {
+ _lastTime++;
+ _lastSequence = 0;
+ }
+
+ return new RuntimeIdStruct(isPool, time, _sceneId, _lastSequence);
}
}
public sealed class RuntimeIdFactoryTool : IIdFactoryTool
{
+ ///
+ /// 获取 RuntimeId 中的 IsPool 标志
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool GetIsPool(long runtimeId)
+ {
+ return GetIsPool(ref runtimeId);
+ }
+
+ ///
+ /// 获取 RuntimeId 中的 IsPool 标志
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool GetIsPool(ref long runtimeId)
+ {
+ return (((ulong)runtimeId >> 63) & 1) == 1; // 最高位
+ }
+
+ ///
+ /// 获取 RuntimeId 中的时间部分
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetTime(ref long runtimeId)
{
- var result = (ulong)runtimeId >> 41;
+ var result = (ulong)runtimeId >> 40; // 右移40位到第40-62位
return (uint)(result & RuntimeIdStruct.MaskTime);
}
-
+
+ ///
+ /// 获取 RuntimeId 中的时间部分
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetTime(long runtimeId)
+ {
+ return GetTime(ref runtimeId);
+ }
+
+ ///
+ /// 获取 RuntimeId 中的 SceneId 部分
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetSceneId(ref long runtimeId)
{
- var result = (ulong)runtimeId >> 25;
+ var result = (ulong)runtimeId >> 24; // 右移24位到第24-39位
return (uint)(result & RuntimeIdStruct.MaskSceneId);
}
+ ///
+ /// 获取 RuntimeId 中的 SceneId 部分
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetSceneId(long runtimeId)
+ {
+ return GetSceneId(ref runtimeId);
+ }
+
+ ///
+ /// 获取 RuntimeId 中的 Sequence 部分
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetSequence(ref long runtimeId)
+ {
+ return (uint)((ulong)runtimeId & RuntimeIdStruct.MaskSequence); // 低24位
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte GetWorldId(ref long entityId)
{
throw new NotImplementedException();
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public byte GetWorldId(long entityId)
+ {
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/IdFactoryHelper.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/IdFactoryHelper.cs
index c60da0b..1d6e141 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/IdFactoryHelper.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/IdFactoryHelper.cs
@@ -118,17 +118,17 @@ namespace Fantasy.IdFactory
}
}
- internal static long RuntimeId(uint time, uint sceneId, byte wordId, uint sequence)
+ internal static long RuntimeId(bool isPool, uint time, uint sceneId, byte wordId, uint sequence)
{
switch (_idFactoryType)
{
case IdFactoryType.Default:
{
- return new RuntimeIdStruct(time, sceneId, sequence);
+ return new RuntimeIdStruct(isPool, time, sceneId, sequence);
}
case IdFactoryType.World:
{
- return new WorldRuntimeIdStruct(time, sceneId, wordId, sequence);
+ return new WorldRuntimeIdStruct(isPool, time, sceneId, wordId, sequence);
}
default:
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Interface/IIdFactory.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Interface/IIdFactory.cs
index d71c15b..8a7af93 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Interface/IIdFactory.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Interface/IIdFactory.cs
@@ -19,6 +19,6 @@ namespace Fantasy.IdFactory
///
/// 创建一个新的Id
///
- public long Create { get; }
+ public long Create(bool isPool);
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Interface/IIdFactoryTool.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Interface/IIdFactoryTool.cs
index 8dd1e99..48676fe 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Interface/IIdFactoryTool.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/Interface/IIdFactoryTool.cs
@@ -5,6 +5,18 @@ namespace Fantasy.IdFactory
///
public interface IIdFactoryTool
{
+ ///
+ /// 获取 RuntimeId 中的 IsPool 标志
+ ///
+ ///
+ ///
+ public bool GetIsPool(ref long runtimeId);
+ ///
+ /// 获取 RuntimeId 中的 IsPool 标志
+ ///
+ ///
+ ///
+ public bool GetIsPool(long runtimeId);
///
/// 获得创建时间
///
@@ -12,16 +24,34 @@ namespace Fantasy.IdFactory
///
public uint GetTime(ref long entityId);
///
+ /// 获得创建时间
+ ///
+ ///
+ ///
+ public uint GetTime(long entityId);
+ ///
/// 获得SceneId
///
///
///
public uint GetSceneId(ref long entityId);
///
+ /// 获得SceneId
+ ///
+ ///
+ ///
+ public uint GetSceneId(long entityId);
+ ///
/// 获得WorldId
///
///
///
public byte GetWorldId(ref long entityId);
+ ///
+ /// 获得WorldId
+ ///
+ ///
+ ///
+ public byte GetWorldId(long entityId);
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/World/WorldEntityIdFactory.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/World/WorldEntityIdFactory.cs
index dbba88f..97241b0 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/World/WorldEntityIdFactory.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/World/WorldEntityIdFactory.cs
@@ -127,6 +127,18 @@ namespace Fantasy.IdFactory
public sealed class WorldEntityIdFactoryTool : IIdFactoryTool
{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool GetIsPool(ref long runtimeId)
+ {
+ throw new NotImplementedException();
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool GetIsPool(long runtimeId)
+ {
+ throw new NotImplementedException();
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetTime(ref long entityId)
{
@@ -134,6 +146,12 @@ namespace Fantasy.IdFactory
return (uint)(result & WorldEntityIdStruct.MaskTime);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetTime(long entityId)
+ {
+ return GetTime(ref entityId);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetSceneId(ref long entityId)
{
@@ -143,11 +161,23 @@ namespace Fantasy.IdFactory
return (uint)(result & WorldEntityIdStruct.MaskSceneId) + worldId;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetSceneId(long entityId)
+ {
+ return GetSceneId(ref entityId);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte GetWorldId(ref long entityId)
{
var result = (ulong)entityId >> 18;
return (byte)(result & WorldEntityIdStruct.MaskWordId);
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public byte GetWorldId(long entityId)
+ {
+ return GetWorldId(ref entityId);
+ }
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/World/WorldRuntimeIdFactory.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/World/WorldRuntimeIdFactory.cs
index a5d582b..3822d9d 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/World/WorldRuntimeIdFactory.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/IdFactory/World/WorldRuntimeIdFactory.cs
@@ -13,30 +13,33 @@ namespace Fantasy.IdFactory
[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个
- // +-------------------+--------------------------+-----------------------+--------------------------------------+
+ // RuntimeId: IsPool(1) + time(23) + SceneId(8) + WordId(8) + sequence(24) = 64 bits
+ // +------------------+-------------------+--------------------------+-----------------------+--------------------------------------+
+ // | IsPool(1) 对象池 | time(23) 最大60天 | SceneId(8) 最多255个Scene | WordId(8) 最多255个世界 | sequence(24) 每秒每个进程能生产16777215个
+ // +------------------+-------------------+--------------------------+-----------------------+--------------------------------------+
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 bool IsPool { get; private set; }
- public const uint MaskSequence = 0x1FFFFFF;
- public const uint MaskSceneId = 0xFF;
- public const uint MaskWordId = 0xFF;
- public const uint MaskTime = 0x7FFFFF;
+ public const uint MaskSequence = 0xFFFFFF; // 24位(从25位减少到24位,为 IsPool 腾出空间)
+ public const uint MaskSceneId = 0xFF; // 8位
+ public const uint MaskWordId = 0xFF; // 8位
+ public const uint MaskTime = 0x7FFFFF; // 23位(最高位留给 IsPool)
///
/// WorldRuntimeIdStruct(如果超过下面参数的设定该ID会失效)。
///
+ /// 是否来自对象池
/// time不能超过8388607
/// sceneId不能超过255
/// wordId不能超过255
- /// sequence不能超过33554431
- public WorldRuntimeIdStruct(uint time, uint sceneId, byte wordId, uint sequence)
+ /// sequence不能超过16777215(24位)
+ public WorldRuntimeIdStruct(bool isPool, uint time, uint sceneId, byte wordId, uint sequence)
{
// 因为都是在配置表里拿到参数、所以这个不做边界判定、能节省一点点性能。
+ IsPool = isPool;
Time = time;
SceneId = sceneId;
WordId = wordId;
@@ -45,26 +48,26 @@ namespace Fantasy.IdFactory
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;
+ ulong result = runtimeIdStruct.Sequence; // 低24位: sequence
+ result |= (ulong)runtimeIdStruct.WordId << 24; // 第24-31位: wordId
+ result |= (ulong)(runtimeIdStruct.SceneId % (runtimeIdStruct.WordId * 1000)) << 32; // 第32-39位: sceneId
+ result |= (ulong)runtimeIdStruct.Time << 40; // 第40-62位: time
+ result |= (runtimeIdStruct.IsPool ? 1UL : 0UL) << 63; // 最高位63: isPool
return (long)result;
}
public static implicit operator WorldRuntimeIdStruct(long runtimeId)
{
var result = (ulong)runtimeId;
+ var wordId = (byte)((result >> 24) & MaskWordId); // 第24-31位: wordId
var runtimeIdStruct = new WorldRuntimeIdStruct
{
- Sequence = (uint)(result & MaskSequence)
+ Sequence = (uint)(result & MaskSequence), // 低24位: sequence
+ WordId = wordId,
+ SceneId = (uint)((result >> 32) & MaskSceneId) + (uint)wordId * 1000, // 第32-39位: sceneId
+ Time = (uint)((result >> 40) & MaskTime), // 第40-62位: time
+ IsPool = ((result >> 63) & 1) == 1 // 最高位63: isPool
};
- 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;
}
}
@@ -105,51 +108,120 @@ namespace Fantasy.IdFactory
}
}
- public long Create
+ public long Create(bool isPool)
{
- get
- {
- var time = (uint)((TimeHelper.Now - _epochNow) / 1000);
-
- if (time > _lastTime)
- {
- _lastTime = time;
- _lastSequence = 0;
- }
- else if (++_lastSequence > WorldRuntimeIdStruct.MaskSequence - 1)
- {
- _lastTime++;
- _lastSequence = 0;
- }
+ var time = (uint)((TimeHelper.Now - _epochNow) / 1000);
- return new WorldRuntimeIdStruct(time, _sceneId, _worldId, _lastSequence);
+ if (time > _lastTime)
+ {
+ _lastTime = time;
+ _lastSequence = 0;
}
+ else if (++_lastSequence > WorldRuntimeIdStruct.MaskSequence - 1)
+ {
+ _lastTime++;
+ _lastSequence = 0;
+ }
+
+ return new WorldRuntimeIdStruct(isPool, time, _sceneId, _worldId, _lastSequence);
}
}
public sealed class WorldRuntimeIdFactoryTool : IIdFactoryTool
{
+ ///
+ /// 获取 RuntimeId 中的 IsPool 标志
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool GetIsPool(long runtimeId)
+ {
+ return GetIsPool(ref runtimeId);
+ }
+
+ ///
+ /// 获取 RuntimeId 中的 IsPool 标志
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool GetIsPool(ref long runtimeId)
+ {
+ return (((ulong)runtimeId >> 63) & 1) == 1; // 最高位
+ }
+
+ ///
+ /// 获取 RuntimeId 中的时间部分
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetTime(ref long runtimeId)
{
- var result = (ulong)runtimeId >> 41;
+ var result = (ulong)runtimeId >> 40; // 右移40位到第40-62位
return (uint)(result & WorldRuntimeIdStruct.MaskTime);
}
-
+
+ ///
+ /// 获取 RuntimeId 中的时间部分
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetTime(long runtimeId)
+ {
+ return GetTime(ref runtimeId);
+ }
+
+ ///
+ /// 获取 RuntimeId 中的 SceneId 部分
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetSceneId(ref long runtimeId)
{
- var result = (ulong)runtimeId >> 25;
- var worldId = (uint)(result & WorldRuntimeIdStruct.MaskWordId) * 1000;
+ var result = (ulong)runtimeId >> 24; // 右移24位
+ var worldId = (uint)(result & WorldRuntimeIdStruct.MaskWordId) * 1000; // 第24-31位: worldId
result >>= 8;
- return (uint)(result & WorldRuntimeIdStruct.MaskSceneId) + worldId;
+ return (uint)(result & WorldRuntimeIdStruct.MaskSceneId) + worldId; // 第32-39位: sceneId
}
+ ///
+ /// 获取 RuntimeId 中的 SceneId 部分
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetSceneId(long runtimeId)
+ {
+ return GetSceneId(ref runtimeId);
+ }
+
+ ///
+ /// 获取 RuntimeId 中的 WorldId 部分
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte GetWorldId(ref long runtimeId)
{
- var result = (ulong)runtimeId >> 25;
+ var result = (ulong)runtimeId >> 24; // 右移24位到第24-31位
return (byte)(result & WorldRuntimeIdStruct.MaskWordId);
}
+
+ ///
+ /// 获取 RuntimeId 中的 WorldId 部分
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public byte GetWorldId(long runtimeId)
+ {
+ return GetWorldId(ref runtimeId);
+ }
+
+ ///
+ /// 获取 RuntimeId 中的 Sequence 部分
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetSequence(ref long runtimeId)
+ {
+ return (uint)((ulong)runtimeId & WorldRuntimeIdStruct.MaskSequence); // 低24位
+ }
+
+ ///
+ /// 获取 RuntimeId 中的 Sequence 部分
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public uint GetSequence(long runtimeId)
+ {
+ return GetSequence(ref runtimeId);
+ }
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Log/Log.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Log/Log.cs
index 3b9cc15..f90557f 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Log/Log.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Log/Log.cs
@@ -2,6 +2,8 @@ using System;
using System.Diagnostics;
#if FANTASY_NET
using Fantasy.Platform.Net;
+// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
+#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
#endif
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
@@ -14,35 +16,27 @@ namespace Fantasy
public static class Log
{
private static ILog _logCore;
- private static bool _isRegister;
-#if FANTASY_NET
+
///
/// 初始化Log系统
///
- public static void Initialize()
+ public static void Initialize(ILog log = null)
{
- if (!_isRegister)
+ if (log == null)
{
- Register(new ConsoleLog());
- return;
- }
-
- _logCore.Initialize(ProgramDefine.RuntimeMode);
- }
+#if FANTASY_NET
+ _logCore = new ConsoleLog();
#endif
- ///
- /// 注册一个日志系统
- ///
- ///
- public static void Register(ILog log)
- {
- if (_isRegister)
- {
+#if FANTASY_UNITY
+ _logCore = new UnityLog();
+#endif
return;
}
_logCore = log;
- _isRegister = true;
+#if FANTASY_NET
+ _logCore.Initialize(ProgramDefine.RuntimeMode);
+#endif
}
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Addressable/AddressableRouteComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Addressable/AddressableRouteComponent.cs
index bf439d7..d31e08f 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Addressable/AddressableRouteComponent.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Addressable/AddressableRouteComponent.cs
@@ -57,12 +57,12 @@ namespace Fantasy.Network.Route
public NetworkMessagingComponent NetworkMessagingComponent;
public MessageDispatcherComponent MessageDispatcherComponent;
- internal void Send(IAddressableRouteMessage message)
+ internal void Send(T message) where T : IAddressableRouteMessage
{
- Call(message).Coroutine();
+ Call(message).Coroutine();
}
- internal async FTask Send(Type requestType, APackInfo packInfo)
+ internal async FTask Send(Type requestType,APackInfo packInfo)
{
await Call(requestType, packInfo);
}
@@ -71,7 +71,7 @@ namespace Fantasy.Network.Route
{
if (IsDisposed)
{
- return MessageDispatcherComponent.CreateResponse(requestType, InnerErrorCode.ErrNotFoundRoute);
+ return MessageDispatcherComponent.CreateResponse(packInfo.ProtocolCode, InnerErrorCode.ErrNotFoundRoute);
}
packInfo.IsDisposed = true;
@@ -92,10 +92,9 @@ namespace Fantasy.Network.Route
if (AddressableRouteId == 0)
{
- return MessageDispatcherComponent.CreateResponse(requestType,
- InnerErrorCode.ErrNotFoundRoute);
+ return MessageDispatcherComponent.CreateResponse(packInfo.ProtocolCode, InnerErrorCode.ErrNotFoundRoute);
}
-
+
iRouteResponse = await NetworkMessagingComponent.CallInnerRoute(AddressableRouteId, requestType, packInfo);
if (runtimeId != RuntimeId)
@@ -148,11 +147,11 @@ namespace Fantasy.Network.Route
/// 调用可寻址路由消息并等待响应。
///
/// 可寻址路由请求。
- private async FTask Call(IAddressableRouteMessage request)
+ private async FTask Call(T request) where T : IAddressableRouteMessage
{
if (IsDisposed)
{
- return MessageDispatcherComponent.CreateResponse(request.GetType(), InnerErrorCode.ErrNotFoundRoute);
+ return MessageDispatcherComponent.CreateResponse(request.OpCode(), InnerErrorCode.ErrNotFoundRoute);
}
var failCount = 0;
@@ -169,8 +168,7 @@ namespace Fantasy.Network.Route
if (AddressableRouteId == 0)
{
- return MessageDispatcherComponent.CreateResponse(request.GetType(),
- InnerErrorCode.ErrNotFoundRoute);
+ return MessageDispatcherComponent.CreateResponse(request.OpCode(), InnerErrorCode.ErrNotFoundRoute);
}
var iRouteResponse = await NetworkMessagingComponent.CallInnerRoute(AddressableRouteId, request);
@@ -186,8 +184,7 @@ namespace Fantasy.Network.Route
{
if (++failCount > 20)
{
- Log.Error(
- $"AddressableRouteComponent.Call failCount > 20 route send message fail, routeId: {RouteId} AddressableRouteComponent:{Id}");
+ Log.Error($"AddressableRouteComponent.Call failCount > 20 route send message fail, routeId: {RouteId} AddressableRouteComponent:{Id}");
return iRouteResponse;
}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Addressable/AddressableScene.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Addressable/AddressableScene.cs
index 3105fca..3835476 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Addressable/AddressableScene.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Addressable/AddressableScene.cs
@@ -24,7 +24,7 @@ namespace Fantasy.Network.Route
public AddressableScene(SceneConfig sceneConfig)
{
Id = IdFactoryHelper.EntityId(0, sceneConfig.Id, (byte)sceneConfig.WorldConfigId, 0);
- RunTimeId = IdFactoryHelper.RuntimeId(0, sceneConfig.Id, (byte)sceneConfig.WorldConfigId, 0);
+ RunTimeId = IdFactoryHelper.RuntimeId(false,0, sceneConfig.Id, (byte)sceneConfig.WorldConfigId, 0);
}
}
}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Dispatcher/Interface/IRouteMessageHandler.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Dispatcher/Interface/IRouteMessageHandler.cs
index 839cf6b..dac9693 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Dispatcher/Interface/IRouteMessageHandler.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Dispatcher/Interface/IRouteMessageHandler.cs
@@ -235,7 +235,7 @@ namespace Fantasy.Network.Interface
}
finally
{
- session.Send(new RouteResponse(), rpcId);
+ session.Send(new RouteResponse(), typeof(RouteResponse), rpcId);
}
}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Dispatcher/MessageDispatcherComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Dispatcher/MessageDispatcherComponent.cs
index 0a24770..44b9ac0 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Dispatcher/MessageDispatcherComponent.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Dispatcher/MessageDispatcherComponent.cs
@@ -1,426 +1,416 @@
using System;
using System.Collections.Generic;
-using System.Threading.Tasks;
using Fantasy.Assembly;
using Fantasy.Async;
-using Fantasy.DataStructure.Collection;
using Fantasy.DataStructure.Dictionary;
using Fantasy.Entitas;
using Fantasy.InnerMessage;
-using Fantasy.Network;
-#pragma warning disable CS8604 // Possible null reference argument.
-
+// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
+// ReSharper disable ForCanBeConvertedToForeach
+// ReSharper disable InvertIf
+#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
+#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
#pragma warning disable CS8602 // Dereference of a possibly null reference.
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
-#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+#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.
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
namespace Fantasy.Network.Interface
{
- ///
- /// 用于存储消息处理器的信息,包括类型和对象实例。
- ///
- /// 消息处理器的类型
- internal sealed class HandlerInfo
+ public sealed class MessageDispatcherComponent : Entity, IAssemblyLifecycle
{
- ///
- /// 获取或设置消息处理器对象。
- ///
- public T Obj;
- ///
- /// 获取或设置消息处理器的类型。
- ///
- public Type Type;
- }
-
- ///
- /// 网络消息分发组件。
- ///
- public sealed class MessageDispatcherComponent : Entity, IAssembly
- {
- public long AssemblyIdentity { get; set; }
- private readonly Dictionary _responseTypes = new Dictionary();
- private readonly DoubleMapDictionary _networkProtocols = new DoubleMapDictionary();
- private readonly Dictionary _messageHandlers = new Dictionary();
- private readonly OneToManyList _assemblyResponseTypes = new OneToManyList();
- private readonly OneToManyList _assemblyNetworkProtocols = new OneToManyList();
- private readonly OneToManyList> _assemblyMessageHandlers = new OneToManyList>();
-#if FANTASY_UNITY
- private readonly Dictionary _messageDelegateHandlers = new Dictionary();
-#endif
-#if FANTASY_NET
- private readonly Dictionary _customRouteMap = new Dictionary();
- private readonly OneToManyList _assemblyCustomRouteMap = new OneToManyList();
- private readonly Dictionary _routeMessageHandlers = new Dictionary();
- private readonly OneToManyList> _assemblyRouteMessageHandlers = new OneToManyList>();
-#endif
private CoroutineLock _receiveRouteMessageLock;
- #region Initialize
+ private readonly HashSet _assemblyManifests = new();
+
+ private Func? _lastHitGetOpCodeType;
+ private Func? _lastHitMessageHandler;
+
+ private readonly List _opCodeResolvers = new List();
+ private readonly List _responseTypeResolvers = new List();
+ private readonly List _messageHandlerResolver = new List();
+#if FANTASY_NET
+ private Func? _lastHitGetCustomRouteType;
+ private Func>? _lastHitRouteMessageHandler;
+ private readonly List _routeMessageHandlerResolver = new List();
+ private readonly List _customRouteResolvers = new List();
+#endif
+
+ #region Comparer
+
+ private class MessageHandlerResolverComparer : IComparer
+ {
+ public int Compare(IMessageHandlerResolver? x, IMessageHandlerResolver? y)
+ {
+ if (x == null || y == null)
+ {
+ return 0;
+ }
+
+ return y.GetMessageHandlerCount().CompareTo(x.GetMessageHandlerCount());
+ }
+ }
+#if FANTASY_NET
+ private class RouteMessageHandlerResolverComparer : IComparer
+ {
+ public int Compare(IMessageHandlerResolver? x, IMessageHandlerResolver? y)
+ {
+ if (x == null || y == null)
+ {
+ return 0;
+ }
+
+ return y.GetRouteMessageHandlerCount().CompareTo(x.GetRouteMessageHandlerCount());
+ }
+ }
+ private class RouteTypeResolverComparer : IComparer
+ {
+ public int Compare(INetworkProtocolOpCodeResolver? x, INetworkProtocolOpCodeResolver? y)
+ {
+ if (x == null || y == null)
+ {
+ return 0;
+ }
+
+ return y.GetCustomRouteTypeCount().CompareTo(x.GetCustomRouteTypeCount());
+ }
+ }
+#endif
+
+ private class OpCodeResolverComparer : IComparer
+ {
+ public int Compare(INetworkProtocolOpCodeResolver? x, INetworkProtocolOpCodeResolver? y)
+ {
+ if (x == null || y == null)
+ {
+ return 0;
+ }
+
+ return y.GetOpCodeCount().CompareTo(x.GetOpCodeCount());
+ }
+ }
+
+ private class ResponseTypeResolverComparer : IComparer
+ {
+ public int Compare(INetworkProtocolResponseTypeResolver? x, INetworkProtocolResponseTypeResolver? y)
+ {
+ if (x == null || y == null)
+ {
+ return 0;
+ }
+
+ return y.GetRequestCount().CompareTo(x.GetRequestCount());
+ }
+ }
+
+ #endregion
+
+ public override void Dispose()
+ {
+ if (IsDisposed)
+ {
+ return;
+ }
+ _assemblyManifests.Clear();
+ _opCodeResolvers.Clear();
+ _responseTypeResolvers.Clear();
+ _receiveRouteMessageLock.Dispose();
+ _messageHandlerResolver.Clear();
+#if FANTASY_NET
+ _customRouteResolvers.Clear();
+ _routeMessageHandlerResolver.Clear();
+ _lastHitGetCustomRouteType = null;
+ _lastHitRouteMessageHandler = null;
+#endif
+ _lastHitGetOpCodeType = null;
+ _lastHitMessageHandler = null;
+ _receiveRouteMessageLock = null;
+ AssemblyLifecycle.Remove(this);
+ base.Dispose();
+ }
+
+ #region AssemblyManifest
internal async FTask Initialize()
{
_receiveRouteMessageLock = Scene.CoroutineLockComponent.Create(GetType().TypeHandle.Value.ToInt64());
- await AssemblySystem.Register(this);
+ await AssemblyLifecycle.Add(this);
return this;
}
- public async FTask Load(long assemblyIdentity)
+ public async FTask OnLoad(AssemblyManifest assemblyManifest)
{
var tcs = FTask.Create(false);
+ var assemblyManifestId = assemblyManifest.AssemblyManifestId;
Scene?.ThreadSynchronizationContext.Post(() =>
{
- LoadInner(assemblyIdentity);
- tcs.SetResult();
- });
- await tcs;
- }
-
- private void LoadInner(long assemblyIdentity)
- {
- // 遍历所有实现了IMessage接口的类型,获取OpCode并添加到_networkProtocols字典中
- foreach (var type in AssemblySystem.ForEach(assemblyIdentity, typeof(IMessage)))
- {
- var obj = (IMessage) Activator.CreateInstance(type);
- var opCode = obj.OpCode();
-
- _networkProtocols.Add(opCode, type);
-
- var responseType = type.GetProperty("ResponseType");
-
- // 如果类型具有ResponseType属性,将其添加到_responseTypes字典中
- if (responseType != null)
+ if (_assemblyManifests.Contains(assemblyManifestId))
{
- _responseTypes.Add(type, responseType.PropertyType);
- _assemblyResponseTypes.Add(assemblyIdentity, type);
+ OnUnLoadInner(assemblyManifest);
}
-
- _assemblyNetworkProtocols.Add(assemblyIdentity, opCode);
- }
-
- // 遍历所有实现了IMessageHandler接口的类型,创建实例并添加到_messageHandlers字典中
- foreach (var type in AssemblySystem.ForEach(assemblyIdentity, typeof(IMessageHandler)))
- {
- var obj = (IMessageHandler) Activator.CreateInstance(type);
-
- if (obj == null)
+ // 注册Handler
+ var messageHandlerResolver = assemblyManifest.MessageHandlerResolver;
+ var messageHandlerCount = messageHandlerResolver.GetMessageHandlerCount();
+ if (messageHandlerCount > 0)
{
- throw new Exception($"message handle {type.Name} is null");
+ _messageHandlerResolver.Add(messageHandlerResolver);
+ _messageHandlerResolver.Sort(new MessageHandlerResolverComparer());
}
-
- var key = obj.Type();
- _messageHandlers.Add(key, obj);
- _assemblyMessageHandlers.Add(assemblyIdentity, new HandlerInfo()
+ // 注册OpCode
+ var opCodeResolver = assemblyManifest.NetworkProtocolOpCodeResolver;
+ var opCodeCount = opCodeResolver.GetOpCodeCount();
+ if (opCodeCount > 0)
{
- Obj = obj, Type = key
- });
- }
-
- // 如果编译符号FANTASY_NET存在,遍历所有实现了IRouteMessageHandler接口的类型,创建实例并添加到_routeMessageHandlers字典中
+ _opCodeResolvers.Add(opCodeResolver);
+ _opCodeResolvers.Sort(new OpCodeResolverComparer());
+ }
#if FANTASY_NET
- foreach (var type in AssemblySystem.ForEach(assemblyIdentity, typeof(IRouteMessageHandler)))
- {
- var obj = (IRouteMessageHandler) Activator.CreateInstance(type);
-
- if (obj == null)
+ var routeMessageHandlerCount = messageHandlerResolver.GetRouteMessageHandlerCount();
+ if (routeMessageHandlerCount > 0)
{
- throw new Exception($"message handle {type.Name} is null");
+ _routeMessageHandlerResolver.Add(messageHandlerResolver);
+ _routeMessageHandlerResolver.Sort(new RouteMessageHandlerResolverComparer());
}
-
- var key = obj.Type();
- _routeMessageHandlers.Add(key, obj);
- _assemblyRouteMessageHandlers.Add(assemblyIdentity, new HandlerInfo()
+ // 注册CustomRouteType
+ var customRouteTypeCount = opCodeResolver.GetCustomRouteTypeCount();
+ if (customRouteTypeCount > 0)
{
- Obj = obj, Type = key
- });
- }
-
- foreach (var type in AssemblySystem.ForEach(assemblyIdentity, typeof(ICustomRoute)))
- {
- var obj = (ICustomRoute) Activator.CreateInstance(type);
-
- if (obj == null)
- {
- throw new Exception($"message handle {type.Name} is null");
+ _customRouteResolvers.Add(opCodeResolver);
+ _customRouteResolvers.Sort(new RouteTypeResolverComparer());
}
-
- var opCode = obj.OpCode();
- _customRouteMap[opCode] = obj.RouteType;
- _assemblyCustomRouteMap.Add(assemblyIdentity, opCode);
- }
#endif
- }
-
- public async FTask ReLoad(long assemblyIdentity)
- {
- var tcs = FTask.Create(false);
- Scene?.ThreadSynchronizationContext.Post(() =>
- {
- OnUnLoadInner(assemblyIdentity);
- LoadInner(assemblyIdentity);
+ // 注册ResponseType
+ var responseTypeResolver = assemblyManifest.NetworkProtocolResponseTypeResolver;
+ var requestCount = responseTypeResolver.GetRequestCount();
+ if (requestCount > 0)
+ {
+ _responseTypeResolvers.Add(responseTypeResolver);
+ _responseTypeResolvers.Sort(new ResponseTypeResolverComparer());
+ }
+ _assemblyManifests.Add(assemblyManifestId);
tcs.SetResult();
});
await tcs;
}
- public async FTask OnUnLoad(long assemblyIdentity)
+ public async FTask OnUnload(AssemblyManifest assemblyManifest)
{
var tcs = FTask.Create(false);
Scene?.ThreadSynchronizationContext.Post(() =>
{
- OnUnLoadInner(assemblyIdentity);
+ OnUnLoadInner(assemblyManifest);
tcs.SetResult();
});
await tcs;
}
- private void OnUnLoadInner(long assemblyIdentity)
+ private void OnUnLoadInner(AssemblyManifest assemblyManifest)
{
- // 移除程序集对应的ResponseType类型和OpCode信息
- if (_assemblyResponseTypes.TryGetValue(assemblyIdentity, out var removeResponseTypes))
- {
- foreach (var removeResponseType in removeResponseTypes)
- {
- _responseTypes.Remove(removeResponseType);
- }
-
- _assemblyResponseTypes.RemoveByKey(assemblyIdentity);
- }
-
- if (_assemblyNetworkProtocols.TryGetValue(assemblyIdentity, out var removeNetworkProtocols))
- {
- foreach (var removeNetworkProtocol in removeNetworkProtocols)
- {
- _networkProtocols.RemoveByKey(removeNetworkProtocol);
- }
-
- _assemblyNetworkProtocols.RemoveByKey(assemblyIdentity);
- }
-
- // 移除程序集对应的消息处理器信息
- if (_assemblyMessageHandlers.TryGetValue(assemblyIdentity, out var removeMessageHandlers))
- {
- foreach (var removeMessageHandler in removeMessageHandlers)
- {
- _messageHandlers.Remove(removeMessageHandler.Type);
- }
-
- _assemblyMessageHandlers.RemoveByKey(assemblyIdentity);
- }
-
- // 如果编译符号FANTASY_NET存在,移除程序集对应的路由消息处理器信息
+ _messageHandlerResolver.Remove(assemblyManifest.MessageHandlerResolver);
+ _opCodeResolvers.Remove(assemblyManifest.NetworkProtocolOpCodeResolver);
+ _responseTypeResolvers.Remove(assemblyManifest.NetworkProtocolResponseTypeResolver);
+ _messageHandlerResolver.Sort(new MessageHandlerResolverComparer());
+ _opCodeResolvers.Sort(new OpCodeResolverComparer());
+ _responseTypeResolvers.Sort(new ResponseTypeResolverComparer());
#if FANTASY_NET
- if (_assemblyRouteMessageHandlers.TryGetValue(assemblyIdentity, out var removeRouteMessageHandlers))
- {
- foreach (var removeRouteMessageHandler in removeRouteMessageHandlers)
- {
- _routeMessageHandlers.Remove(removeRouteMessageHandler.Type);
- }
-
- _assemblyRouteMessageHandlers.RemoveByKey(assemblyIdentity);
- }
-
- if (_assemblyCustomRouteMap.TryGetValue(assemblyIdentity, out var removeCustomRouteMap))
- {
- foreach (var removeCustom in removeCustomRouteMap)
- {
- _customRouteMap.Remove(removeCustom);
- }
-
- _assemblyCustomRouteMap.RemoveByKey(assemblyIdentity);
- }
+ _routeMessageHandlerResolver.Remove(assemblyManifest.MessageHandlerResolver);
+ _customRouteResolvers.Remove(assemblyManifest.NetworkProtocolOpCodeResolver);
+ _routeMessageHandlerResolver.Sort(new RouteMessageHandlerResolverComparer());
+ _customRouteResolvers.Sort(new RouteTypeResolverComparer());
#endif
- }
-
-#if FANTASY_UNITY
- ///
- /// 手动注册一个消息处理器。
- ///
- ///
- ///
- public void RegisterHandler(MessageDelegate @delegate) where T : IMessage
- {
- var type = typeof(T);
-
- if (!_messageDelegateHandlers.TryGetValue(type, out var messageDelegate))
- {
- messageDelegate = new MessageDelegateHandler();
- _messageDelegateHandlers.Add(type,messageDelegate);
- }
-
- messageDelegate.Register(@delegate);
+ _assemblyManifests.Remove(assemblyManifest.AssemblyManifestId);
}
- ///
- /// 手动卸载一个消息处理器,必须是通过RegisterHandler方法注册的消息处理器。
- ///
- ///
- ///
- public void UnRegisterHandler(MessageDelegate @delegate) where T : IMessage
- {
- var type = typeof(T);
-
- if (!_messageDelegateHandlers.TryGetValue(type, out var messageDelegate))
- {
- return;
- }
-
- if (messageDelegate.UnRegister(@delegate) != 0)
- {
- return;
- }
-
- _messageDelegateHandlers.Remove(type);
- }
-#endif
#endregion
-
- ///
- /// 处理普通消息,将消息分发给相应的消息处理器。
- ///
- /// 会话对象
- /// 消息类型
- /// 消息对象
- /// RPC标识
- /// 协议码
- public void MessageHandler(Session session, Type type, object message, uint rpcId, uint protocolCode)
+
+ internal void MessageHandler(Session session, Type type, object message, uint rpcId, uint protocolCode)
{
-#if FANTASY_UNITY
- if(_messageDelegateHandlers.TryGetValue(type,out var messageDelegateHandler))
+ if (_lastHitMessageHandler != null &&
+ _lastHitMessageHandler(session, rpcId, protocolCode, message))
{
- messageDelegateHandler.Handle(session, message);
- return;
- }
-#endif
- if (!_messageHandlers.TryGetValue(type, out var messageHandler))
- {
- Log.Warning($"Scene:{session.Scene.Id} Found Unhandled Message: {message.GetType()}");
return;
}
- // 调用消息处理器的Handle方法并启动协程执行处理逻辑
- messageHandler.Handle(session, rpcId, protocolCode, message).Coroutine();
- }
-
- // 如果编译符号FANTASY_NET存在,定义处理路由消息的方法
-#if FANTASY_NET
- ///
- /// 处理路由消息,将消息分发给相应的路由消息处理器。
- ///
- /// 会话对象
- /// 消息类型
- /// 实体对象
- /// 消息对象
- /// RPC标识
- public async FTask RouteMessageHandler(Session session, Type type, Entity entity, object message, uint rpcId)
- {
- if (!_routeMessageHandlers.TryGetValue(type, out var routeMessageHandler))
+ for (var i = 0; i < _messageHandlerResolver.Count; i++)
{
- Log.Warning($"Scene:{session.Scene.Id} Found Unhandled RouteMessage: {message.GetType()}");
-
- if (message is IRouteRequest request)
+ var resolver = _messageHandlerResolver[i];
+ if (resolver.MessageHandler(session, rpcId, protocolCode, message))
{
- FailRouteResponse(session, request.GetType(), InnerErrorCode.ErrEntityNotFound, rpcId);
+ _lastHitMessageHandler = resolver.MessageHandler;
+ return;
}
-
- return;
}
- var runtimeId = entity.RuntimeId;
- var sessionRuntimeId = session.RuntimeId;
+ Log.Warning($"Scene:{session.Scene.Id} Found Unhandled Message: {type}");
+ }
+#if FANTASY_NET
+ private async FTask InnerRouteMessageHandler(Session session, Entity entity, uint rpcId, uint protocolCode, object message)
+ {
+ if (_lastHitRouteMessageHandler != null &&
+ await _lastHitRouteMessageHandler(session, entity, rpcId, protocolCode, message))
+ {
+ return true;
+ }
+ for (var i = 0; i < _routeMessageHandlerResolver.Count; i++)
+ {
+ var resolver = _routeMessageHandlerResolver[i];
+ if (await resolver.RouteMessageHandler(session, entity, rpcId, protocolCode, message))
+ {
+ _lastHitRouteMessageHandler = resolver.RouteMessageHandler;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ internal async FTask RouteMessageHandler(Session session, Type type, Entity entity, object message, uint rpcId, uint protocolCode)
+ {
if (entity is Scene)
{
// 如果是Scene的话、就不要加锁了、如果加锁很一不小心就可能会造成死锁
- await routeMessageHandler.Handle(session, entity, rpcId, message);
+ if (!await InnerRouteMessageHandler(session, entity, rpcId, protocolCode, message))
+ {
+ Log.Warning($"Scene:{session.Scene.Id} Found Unhandled RouteMessage: {type}");
+ }
return;
}
- // 使用协程锁来确保多线程安全
+ // 使用协程锁来确保消息的顺序
+ var runtimeId = entity.RuntimeId;
+ var sessionRuntimeId = session.RuntimeId;
using (await _receiveRouteMessageLock.Wait(runtimeId))
{
if (sessionRuntimeId != session.RuntimeId)
{
return;
}
-
+
if (runtimeId != entity.RuntimeId)
{
if (message is IRouteRequest request)
{
- FailRouteResponse(session, request.GetType(), InnerErrorCode.ErrEntityNotFound, rpcId);
+ FailRouteResponse(session, request.OpCode(), InnerErrorCode.ErrEntityNotFound, rpcId);
}
-
+
return;
}
- await routeMessageHandler.Handle(session, entity, rpcId, message);
+ if (!await InnerRouteMessageHandler(session, entity, rpcId, protocolCode, message))
+ {
+ Log.Warning($"Scene:{session.Scene.Id} Found Unhandled RouteMessage: {message.GetType()}");
+ }
}
}
-
- internal bool GetCustomRouteType(long protocolCode, out int routeType)
- {
- return _customRouteMap.TryGetValue(protocolCode, out routeType);
- }
#endif
- internal void FailRouteResponse(Session session, Type requestType, uint error, uint rpcId)
+ #region Response
+
+ internal void FailRouteResponse(Session session, uint requestOpCode, uint error, uint rpcId)
{
- var response = CreateRouteResponse(requestType, error);
- session.Send(response, rpcId);
+ session.Send(CreateRouteResponse(requestOpCode, error, out var responseType), responseType, rpcId);
}
-
- internal IResponse CreateResponse(Type requestType, uint error)
+
+ internal IResponse CreateResponse(uint requestOpCode, uint error)
{
IResponse response;
- if (_responseTypes.TryGetValue(requestType, out var responseType))
+ for (var i = 0; i < _responseTypeResolvers.Count; i++)
{
+ var resolver = _responseTypeResolvers[i];
+ var responseType = resolver.GetResponseType(requestOpCode);
+ if (responseType == null)
+ {
+ continue;
+ }
response = (IResponse) Activator.CreateInstance(responseType);
+ response.ErrorCode = error;
+ return response;
}
- else
- {
- response = new Response();
- }
-
+
+ response = new Response();
response.ErrorCode = error;
return response;
}
-
- internal IRouteResponse CreateRouteResponse(Type requestType, uint error)
+
+ private IRouteResponse CreateRouteResponse(uint requestOpCode, uint error, out Type responseType)
{
IRouteResponse response;
- if (_responseTypes.TryGetValue(requestType, out var responseType))
+ for (var i = 0; i < _responseTypeResolvers.Count; i++)
{
- response = (IRouteResponse) Activator.CreateInstance(responseType);
- }
- else
- {
- response = new RouteResponse();
+ var resolver = _responseTypeResolvers[i];
+ responseType = resolver.GetResponseType(requestOpCode);
+ if (responseType == null)
+ {
+ continue;
+ }
+
+ response = (IRouteResponse)Activator.CreateInstance(responseType);
+ response.ErrorCode = error;
+ return response;
}
+ responseType = typeof(RouteResponse);
+ response = new RouteResponse();
response.ErrorCode = error;
return response;
}
-
- ///
- /// 根据消息类型获取对应的OpCode。
- ///
- /// 消息类型
- /// 消息对应的OpCode
- public uint GetOpCode(Type type)
- {
- return _networkProtocols.GetKeyByValue(type);
- }
- ///
- /// 根据OpCode获取对应的消息类型。
- ///
- /// OpCode
- /// OpCode对应的消息类型
- public Type GetOpCodeType(uint code)
+ #endregion
+
+ #region OpCode
+
+ internal Type? GetOpCodeType(uint opCode)
{
- return _networkProtocols.GetValueByKey(code);
+ if (_lastHitGetOpCodeType != null )
+ {
+ var opCodeType = _lastHitGetOpCodeType(opCode);
+ if (opCodeType != null)
+ {
+ return opCodeType;
+ }
+ }
+
+ for (var i = 0; i < _opCodeResolvers.Count; i++)
+ {
+ var resolver = _opCodeResolvers[i];
+ var opCodeType = resolver.GetOpCodeType(opCode);
+ if (opCodeType != null)
+ {
+ _lastHitGetOpCodeType = resolver.GetOpCodeType;
+ return opCodeType;
+ }
+ }
+
+ return null;
}
+#if FANTASY_NET
+ internal int? GetCustomRouteType(uint protocolCode)
+ {
+ if (_lastHitGetCustomRouteType != null)
+ {
+ var opCodeType = _lastHitGetCustomRouteType(protocolCode);
+ if (opCodeType.HasValue)
+ {
+ return opCodeType.Value;
+ }
+ }
+
+ for (var i = 0; i < _customRouteResolvers.Count; i++)
+ {
+ var resolver = _customRouteResolvers[i];
+ var opCodeType = resolver.GetCustomRouteType(protocolCode);
+ if (opCodeType.HasValue)
+ {
+ _lastHitGetCustomRouteType = resolver.GetCustomRouteType;
+ return opCodeType.Value;
+ }
+ }
+
+ return null;
+ }
+#endif
+ #endregion
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/IMessage.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/IMessage.cs
index aea7d08..67c22cc 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/IMessage.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/IMessage.cs
@@ -1,8 +1,53 @@
using System;
+using System.Runtime.Serialization;
+using Fantasy.Async;
+using Fantasy.Pool;
+using Fantasy.Serialize;
+using MongoDB.Bson.Serialization.Attributes;
+using Newtonsoft.Json;
+using ProtoBuf;
+#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.
+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
namespace Fantasy.Network.Interface
{
+ public abstract class AMessage : ASerialize, IPool
+ {
+#if FANTASY_NET || FANTASY_UNITY || FANTASY_CONSOLE
+ [BsonIgnore]
+ [JsonIgnore]
+ [IgnoreDataMember]
+ [ProtoIgnore]
+ private Scene _scene;
+ protected Scene GetScene()
+ {
+ return _scene;
+ }
+
+ public void SetScene(Scene scene)
+ {
+ _scene = scene;
+ }
+#endif
+#if FANTASY_NET
+ [BsonIgnore]
+#endif
+ [JsonIgnore]
+ [IgnoreDataMember]
+ [ProtoIgnore]
+ private bool _isPool;
+
+ public bool IsPool()
+ {
+ return _isPool;
+ }
+
+ public void SetIsPool(bool isPool)
+ {
+ _isPool = isPool;
+ }
+ }
///
/// 表示通用消息接口。
///
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/InnerMessage.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/InnerMessage.cs
index 643c92b..f621bcc 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/InnerMessage.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/InnerMessage.cs
@@ -21,6 +21,7 @@ namespace Fantasy.InnerMessage
return Fantasy.Network.OpCode.BenchmarkMessage;
}
}
+
[ProtoContract]
public partial class BenchmarkRequest : AMessage, IRequest
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/BufferPacketParser.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/BufferPacketParser.cs
index b1c6c84..427fe97 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/BufferPacketParser.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/BufferPacketParser.cs
@@ -96,9 +96,9 @@ namespace Fantasy.PacketParser
return true;
}
- public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- return memoryStream == null ? Pack(ref rpcId, ref routeId, message) : Pack(ref rpcId, ref routeId, memoryStream);
+ return memoryStream == null ? Pack(ref rpcId, ref routeId, message, messageType) : Pack(ref rpcId, ref routeId, memoryStream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -114,12 +114,12 @@ namespace Fantasy.PacketParser
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, IMessage message)
+ private MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, IMessage message, Type messageType)
{
var memoryStreamLength = 0;
- var messageType = message.GetType();
var memoryStream = Network.MemoryStreamBufferPool.RentMemoryStream(MemoryStreamBufferSource.Pack);
- OpCodeIdStruct opCodeIdStruct = message.OpCode();
+ var opCode = message.OpCode();
+ OpCodeIdStruct opCodeIdStruct = opCode;
memoryStream.Seek(Packet.InnerPacketHeadLength, SeekOrigin.Begin);
if (SerializerManager.TryGetSerializer(opCodeIdStruct.OpCodeProtocolType, out var serializer))
@@ -131,8 +131,7 @@ namespace Fantasy.PacketParser
{
Log.Error($"type:{messageType} Does not support processing protocol");
}
-
- var opCode = Scene.MessageDispatcherComponent.GetOpCode(messageType);
+
var packetBodyCount = memoryStreamLength - Packet.InnerPacketHeadLength;
if (packetBodyCount == 0)
@@ -209,9 +208,9 @@ namespace Fantasy.PacketParser
return true;
}
- public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- return memoryStream == null ? Pack(ref rpcId, message) : Pack(ref rpcId, memoryStream);
+ return memoryStream == null ? Pack(ref rpcId, message, messageType) : Pack(ref rpcId, memoryStream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -228,12 +227,12 @@ namespace Fantasy.PacketParser
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private MemoryStreamBuffer Pack(ref uint rpcId, IMessage message)
+ private MemoryStreamBuffer Pack(ref uint rpcId, IMessage message, Type messageType)
{
var memoryStreamLength = 0;
- var messageType = message.GetType();
var memoryStream = Network.MemoryStreamBufferPool.RentMemoryStream(MemoryStreamBufferSource.Pack);
- OpCodeIdStruct opCodeIdStruct = message.OpCode();
+ var opCode = message.OpCode();
+ OpCodeIdStruct opCodeIdStruct = opCode;
memoryStream.Seek(Packet.OuterPacketHeadLength, SeekOrigin.Begin);
if (SerializerManager.TryGetSerializer(opCodeIdStruct.OpCodeProtocolType, out var serializer))
@@ -246,7 +245,8 @@ namespace Fantasy.PacketParser
Log.Error($"type:{messageType} Does not support processing protocol");
}
- var opCode = Scene.MessageDispatcherComponent.GetOpCode(messageType);
+
+ // var opCode = Scene.MessageDispatcherComponent.GetOpCode(messageType);
var packetBodyCount = memoryStreamLength - Packet.OuterPacketHeadLength;
if (packetBodyCount == 0)
@@ -324,9 +324,9 @@ namespace Fantasy.PacketParser
return true;
}
- public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- return memoryStream == null ? Pack(ref rpcId, message) : Pack(ref rpcId, memoryStream);
+ return memoryStream == null ? Pack(ref rpcId, message, messageType) : Pack(ref rpcId, memoryStream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -343,12 +343,12 @@ namespace Fantasy.PacketParser
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private MemoryStreamBuffer Pack(ref uint rpcId, IMessage message)
+ private MemoryStreamBuffer Pack(ref uint rpcId, IMessage message, Type messageType)
{
var memoryStreamLength = 0;
- var messageType = message.GetType();
var memoryStream = Network.MemoryStreamBufferPool.RentMemoryStream(MemoryStreamBufferSource.UnPack);
- OpCodeIdStruct opCodeIdStruct = message.OpCode();
+ var opCode = message.OpCode();
+ OpCodeIdStruct opCodeIdStruct = opCode;
memoryStream.Seek(Packet.OuterPacketHeadLength, SeekOrigin.Begin);
if (SerializerManager.TryGetSerializer(opCodeIdStruct.OpCodeProtocolType, out var serializer))
@@ -361,7 +361,6 @@ namespace Fantasy.PacketParser
Log.Error($"type:{messageType} Does not support processing protocol");
}
- var opCode = Scene.MessageDispatcherComponent.GetOpCode(messageType);
var packetBodyCount = memoryStreamLength - Packet.OuterPacketHeadLength;
if (packetBodyCount == 0)
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/OuterBufferPacketParserHelper.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/OuterBufferPacketParserHelper.cs
index 0047c39..49b4186 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/OuterBufferPacketParserHelper.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/OuterBufferPacketParserHelper.cs
@@ -19,17 +19,18 @@ namespace Fantasy.PacketParser
/// scene
/// 如果是RPC消息需要传递一个rpcId
/// 打包的网络消息
+ /// 打包的网络消息类型
/// 序列化后流的长度
/// 打包完成会返回一个MemoryStreamBuffer
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static MemoryStreamBuffer Pack(Scene scene, uint rpcId, IMessage message, out int memoryStreamLength)
+ public static MemoryStreamBuffer Pack(Scene scene, uint rpcId, IMessage message, Type messageType, out int memoryStreamLength)
{
memoryStreamLength = 0;
- var messageType = message.GetType();
var memoryStream = new MemoryStreamBuffer();
memoryStream.MemoryStreamBufferSource = MemoryStreamBufferSource.Pack;
- OpCodeIdStruct opCodeIdStruct = message.OpCode();
+ var opCode = message.OpCode();
+ OpCodeIdStruct opCodeIdStruct = opCode;
memoryStream.Seek(Packet.OuterPacketHeadLength, SeekOrigin.Begin);
if (SerializerManager.TryGetSerializer(opCodeIdStruct.OpCodeProtocolType, out var serializer))
@@ -41,8 +42,7 @@ namespace Fantasy.PacketParser
{
Log.Error($"type:{messageType} Does not support processing protocol");
}
-
- var opCode = scene.MessageDispatcherComponent.GetOpCode(messageType);
+ ;
var packetBodyCount = memoryStreamLength - Packet.OuterPacketHeadLength;
if (packetBodyCount == 0)
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/ReadOnlyMemoryPacketParser.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/ReadOnlyMemoryPacketParser.cs
index dc2203b..34e491b 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/ReadOnlyMemoryPacketParser.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Handler/ReadOnlyMemoryPacketParser.cs
@@ -143,9 +143,9 @@ namespace Fantasy.PacketParser
return false;
}
- public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- return memoryStream == null ? Pack(ref rpcId, ref routeId, message) : Pack(ref rpcId, ref routeId, memoryStream);
+ return memoryStream == null ? Pack(ref rpcId, ref routeId, message, messageType) : Pack(ref rpcId, ref routeId, memoryStream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -161,12 +161,12 @@ namespace Fantasy.PacketParser
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, IMessage message)
+ private MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, IMessage message, Type messageType)
{
var memoryStreamLength = 0;
- var messageType = message.GetType();
var memoryStream = Network.MemoryStreamBufferPool.RentMemoryStream(MemoryStreamBufferSource.Pack);
- OpCodeIdStruct opCodeIdStruct = message.OpCode();
+ var opCode = message.OpCode();
+ OpCodeIdStruct opCodeIdStruct = opCode;
memoryStream.Seek(Packet.InnerPacketHeadLength, SeekOrigin.Begin);
if (SerializerManager.TryGetSerializer(opCodeIdStruct.OpCodeProtocolType, out var serializer))
@@ -179,7 +179,7 @@ namespace Fantasy.PacketParser
Log.Error($"type:{messageType} Does not support processing protocol");
}
- var opCode = Scene.MessageDispatcherComponent.GetOpCode(messageType);
+
var packetBodyCount = memoryStreamLength - Packet.InnerPacketHeadLength;
if (packetBodyCount == 0)
@@ -306,9 +306,9 @@ namespace Fantasy.PacketParser
return false;
}
- public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- return memoryStream == null ? Pack(ref rpcId, message) : Pack(ref rpcId, memoryStream);
+ return memoryStream == null ? Pack(ref rpcId, message, messageType) : Pack(ref rpcId, memoryStream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -326,12 +326,12 @@ namespace Fantasy.PacketParser
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private unsafe MemoryStreamBuffer Pack(ref uint rpcId, IMessage message)
+ private unsafe MemoryStreamBuffer Pack(ref uint rpcId, IMessage message, Type messageType)
{
var memoryStreamLength = 0;
- var messageType = message.GetType();
var memoryStream = Network.MemoryStreamBufferPool.RentMemoryStream(MemoryStreamBufferSource.Pack);
- OpCodeIdStruct opCodeIdStruct = message.OpCode();
+ var opCode = message.OpCode();
+ OpCodeIdStruct opCodeIdStruct = opCode;
memoryStream.Seek(Packet.OuterPacketHeadLength, SeekOrigin.Begin);
if (SerializerManager.TryGetSerializer(opCodeIdStruct.OpCodeProtocolType, out var serializer))
@@ -344,7 +344,7 @@ namespace Fantasy.PacketParser
Log.Error($"type:{messageType} Does not support processing protocol");
}
- var opCode = Scene.MessageDispatcherComponent.GetOpCode(messageType);
+
var packetBodyCount = memoryStreamLength - Packet.OuterPacketHeadLength;
if (packetBodyCount == 0)
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Interface/APacketParser.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Interface/APacketParser.cs
index 579cf6f..132689b 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Interface/APacketParser.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Interface/APacketParser.cs
@@ -19,7 +19,7 @@ namespace Fantasy.PacketParser.Interface
internal ANetwork Network;
internal MessageDispatcherComponent MessageDispatcherComponent;
protected bool IsDisposed { get; private set; }
- public abstract MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message);
+ public abstract MemoryStreamBuffer Pack(ref uint rpcId, ref long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType);
public virtual void Dispose()
{
IsDisposed = true;
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/OpCode.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/OpCode.cs
index 27c5dbb..1cd325e 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/OpCode.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/OpCode.cs
@@ -86,37 +86,43 @@ namespace Fantasy.Network
public static class OpCode
{
- public static readonly uint BenchmarkMessage = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.OuterMessage, 8388607);
- public static readonly uint BenchmarkRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.OuterRequest, 8388607);
- public static readonly uint BenchmarkResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.OuterResponse, 8388607);
- public static readonly uint PingRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.OuterPingRequest, 1);
- public static readonly uint PingResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.OuterPingResponse, 1);
- public static readonly uint DefaultResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerResponse, 1);
- public static readonly uint DefaultRouteResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 7);
- public static readonly uint AddressableAddRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 1);
- public static readonly uint AddressableAddResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 1);
- public static readonly uint AddressableGetRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 2);
- public static readonly uint AddressableGetResponse = Create(OpCodeProtocolType.ProtoBuf,OpCodeType.InnerRouteResponse,2);
- public static readonly uint AddressableRemoveRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 3);
- public static readonly uint AddressableRemoveResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 3);
- public static readonly uint AddressableLockRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 4);
- public static readonly uint AddressableLockResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 4);
- public static readonly uint AddressableUnLockRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 5);
- public static readonly uint AddressableUnLockResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 5);
- public static readonly uint LinkRoamingRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 6);
- public static readonly uint LinkRoamingResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 6);
- public static readonly uint UnLinkRoamingRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 8);
- public static readonly uint UnLinkRoamingResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 8);
- public static readonly uint LockTerminusIdRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 9);
- public static readonly uint LockTerminusIdResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 9);
- public static readonly uint UnLockTerminusIdRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 10);
- public static readonly uint UnLockTerminusIdResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 10);
- public static readonly uint GetTerminusIdRequest = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteRequest, 11);
- public static readonly uint GetTerminusIdResponse = Create(OpCodeProtocolType.ProtoBuf, OpCodeType.InnerRouteResponse, 11);
-
- public static readonly uint TransferTerminusRequest = Create(OpCodeProtocolType.Bson, OpCodeType.InnerRouteRequest, 1);
- public static readonly uint TransferTerminusResponse = Create(OpCodeProtocolType.Bson, OpCodeType.InnerRouteResponse, 1);
-
+ // 格式: Index | (OpCodeProtocolType << 23) | (Protocol << 27)
+ // 所有值已预先计算,使 SourceGenerator 可以在编译时获取这些常量
+
+ public const uint BenchmarkMessage = 142606335; // Create(ProtoBuf=0, OuterMessage=1, 8388607)
+ public const uint BenchmarkRequest = 276824063; // Create(ProtoBuf=0, OuterRequest=2, 8388607)
+ public const uint BenchmarkResponse = 411041791; // Create(ProtoBuf=0, OuterResponse=3, 8388607)
+ public const uint PingRequest = 4026531841; // Create(ProtoBuf=0, OuterPingRequest=30, 1)
+ public const uint PingResponse = 4160749569; // Create(ProtoBuf=0, OuterPingResponse=31, 1)
+ public const uint DefaultResponse = 805306369; // Create(ProtoBuf=0, InnerResponse=6, 1)
+ public const uint DefaultRouteResponse = 1207959559; // Create(ProtoBuf=0, InnerRouteResponse=9, 7)
+ public const uint AddressableAddRequest = 1073741825; // Create(ProtoBuf=0, InnerRouteRequest=8, 1)
+ public const uint AddressableAddResponse = 1207959553; // Create(ProtoBuf=0, InnerRouteResponse=9, 1)
+ public const uint AddressableGetRequest = 1073741826; // Create(ProtoBuf=0, InnerRouteRequest=8, 2)
+ public const uint AddressableGetResponse = 1207959554; // Create(ProtoBuf=0, InnerRouteResponse=9, 2)
+ public const uint AddressableRemoveRequest = 1073741827; // Create(ProtoBuf=0, InnerRouteRequest=8, 3)
+ public const uint AddressableRemoveResponse = 1207959555; // Create(ProtoBuf=0, InnerRouteResponse=9, 3)
+ public const uint AddressableLockRequest = 1073741828; // Create(ProtoBuf=0, InnerRouteRequest=8, 4)
+ public const uint AddressableLockResponse = 1207959556; // Create(ProtoBuf=0, InnerRouteResponse=9, 4)
+ public const uint AddressableUnLockRequest = 1073741829; // Create(ProtoBuf=0, InnerRouteRequest=8, 5)
+ public const uint AddressableUnLockResponse = 1207959557; // Create(ProtoBuf=0, InnerRouteResponse=9, 5)
+ public const uint LinkRoamingRequest = 1073741830; // Create(ProtoBuf=0, InnerRouteRequest=8, 6)
+ public const uint LinkRoamingResponse = 1207959558; // Create(ProtoBuf=0, InnerRouteResponse=9, 6)
+ public const uint UnLinkRoamingRequest = 1073741832; // Create(ProtoBuf=0, InnerRouteRequest=8, 8)
+ public const uint UnLinkRoamingResponse = 1207959560; // Create(ProtoBuf=0, InnerRouteResponse=9, 8)
+ public const uint LockTerminusIdRequest = 1073741833; // Create(ProtoBuf=0, InnerRouteRequest=8, 9)
+ public const uint LockTerminusIdResponse = 1207959561; // Create(ProtoBuf=0, InnerRouteResponse=9, 9)
+ public const uint UnLockTerminusIdRequest = 1073741834; // Create(ProtoBuf=0, InnerRouteRequest=8, 10)
+ public const uint UnLockTerminusIdResponse = 1207959562; // Create(ProtoBuf=0, InnerRouteResponse=9, 10)
+ public const uint GetTerminusIdRequest = 1073741835; // Create(ProtoBuf=0, InnerRouteRequest=8, 11)
+ public const uint GetTerminusIdResponse = 1207959563; // Create(ProtoBuf=0, InnerRouteResponse=9, 11)
+
+ public const uint TransferTerminusRequest = 1082130433; // Create(Bson=1, InnerRouteRequest=8, 1)
+ public const uint TransferTerminusResponse = 1216348161; // Create(Bson=1, InnerRouteResponse=9, 1)
+
+ ///
+ /// 创建 OpCode(运行时使用)
+ ///
public static uint Create(uint opCodeProtocolType, uint protocol, uint index)
{
return new OpCodeIdStruct(opCodeProtocolType, protocol, index);
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Pack/InnerPackInfo.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Pack/InnerPackInfo.cs
index e9870e7..d01538f 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Pack/InnerPackInfo.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Pack/InnerPackInfo.cs
@@ -14,7 +14,7 @@ namespace Fantasy.PacketParser
{
public sealed class InnerPackInfo : APackInfo
{
- private readonly Dictionary> _createInstances = new Dictionary>();
+ private readonly Dictionary> _createInstances = new Dictionary>();
public override void Dispose()
{
@@ -53,13 +53,13 @@ namespace Fantasy.PacketParser
if (MemoryStream.Length == 0)
{
- if (_createInstances.TryGetValue(messageType, out var createInstance))
+ if (_createInstances.TryGetValue(messageType.TypeHandle, out var createInstance))
{
return createInstance();
}
createInstance = CreateInstance.CreateObject(messageType);
- _createInstances.Add(messageType, createInstance);
+ _createInstances.Add(messageType.TypeHandle, createInstance);
return createInstance();
}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Pack/ProcessPackInfo.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Pack/ProcessPackInfo.cs
index fb28df6..adf062a 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Pack/ProcessPackInfo.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/PacketParser/Pack/ProcessPackInfo.cs
@@ -19,7 +19,7 @@ namespace Fantasy.PacketParser
private int _disposeCount;
public Type MessageType { get; private set; }
private static readonly ConcurrentQueue Caches = new ConcurrentQueue();
- private readonly ConcurrentDictionary> _createInstances = new ConcurrentDictionary>();
+ private readonly ConcurrentDictionary> _createInstances = new ConcurrentDictionary>();
public override void Dispose()
{
@@ -54,7 +54,8 @@ namespace Fantasy.PacketParser
packInfo.IsDisposed = false;
var memoryStream = new MemoryStreamBuffer();
memoryStream.MemoryStreamBufferSource = MemoryStreamBufferSource.Pack;
- OpCodeIdStruct opCodeIdStruct = message.OpCode();
+ var opCode = message.OpCode();
+ OpCodeIdStruct opCodeIdStruct = opCode;
memoryStream.Seek(Packet.InnerPacketHeadLength, SeekOrigin.Begin);
if (SerializerManager.TryGetSerializer(opCodeIdStruct.OpCodeProtocolType, out var serializer))
@@ -66,8 +67,7 @@ namespace Fantasy.PacketParser
{
Log.Error($"type:{type} Does not support processing protocol");
}
-
- var opCode = scene.MessageDispatcherComponent.GetOpCode(packInfo.MessageType);
+
var packetBodyCount = memoryStreamLength - Packet.InnerPacketHeadLength;
if (packetBodyCount == 0)
@@ -128,25 +128,24 @@ namespace Fantasy.PacketParser
Log.Debug("Deserialize MemoryStream is null");
return null;
}
-
- object obj = null;
+
+ var messageTypeTypeHandle = messageType.TypeHandle;
MemoryStream.Seek(Packet.InnerPacketHeadLength, SeekOrigin.Begin);
-
if (MemoryStream.Length == 0)
{
- if (_createInstances.TryGetValue(messageType, out var createInstance))
+ if (_createInstances.TryGetValue(messageTypeTypeHandle, out var createInstance))
{
return createInstance();
}
createInstance = CreateInstance.CreateObject(messageType);
- _createInstances.TryAdd(messageType, createInstance);
+ _createInstances.TryAdd(messageTypeTypeHandle, createInstance);
return createInstance();
}
if (SerializerManager.TryGetSerializer(OpCodeIdStruct.OpCodeProtocolType, out var serializer))
{
- obj = serializer.Deserialize(messageType, MemoryStream);
+ var obj = serializer.Deserialize(messageType, MemoryStream);
MemoryStream.Seek(0, SeekOrigin.Begin);
return obj;
}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/InnerMessageScheduler.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/InnerMessageScheduler.cs
index b1b55f6..275ecd3 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/InnerMessageScheduler.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/InnerMessageScheduler.cs
@@ -6,6 +6,7 @@ using Fantasy.Network;
using Fantasy.Network.Interface;
using Fantasy.PacketParser;
using Fantasy.PacketParser.Interface;
+#pragma warning disable CS8602 // Dereference of a possibly null reference.
#pragma warning disable CS8604 // Possible null reference argument.
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
@@ -85,12 +86,12 @@ namespace Fantasy.Scheduler
if (!Scene.TryGetEntity(packInfo.RouteId, out var entity))
{
- Scene.MessageDispatcherComponent.FailRouteResponse(session, messageType, InnerErrorCode.ErrNotFoundRoute, packInfo.RpcId);
+ Scene.MessageDispatcherComponent.FailRouteResponse(session, packInfo.ProtocolCode, InnerErrorCode.ErrNotFoundRoute, packInfo.RpcId);
return;
}
var obj = packInfo.Deserialize(messageType);
- await Scene.MessageDispatcherComponent.RouteMessageHandler(session, messageType, entity, (IMessage)obj, packInfo.RpcId);
+ await Scene.MessageDispatcherComponent.RouteMessageHandler(session, messageType, entity, (IMessage)obj, packInfo.RpcId, packInfo.ProtocolCode);
}
return;
@@ -110,12 +111,12 @@ namespace Fantasy.Scheduler
if (!Scene.TryGetEntity(packInfo.RouteId, out var entity))
{
- Scene.MessageDispatcherComponent.FailRouteResponse(session, messageType, InnerErrorCode.ErrNotFoundRoute, packInfo.RpcId);
+ Scene.MessageDispatcherComponent.FailRouteResponse(session, packInfo.ProtocolCode, InnerErrorCode.ErrNotFoundRoute, packInfo.RpcId);
return;
}
var obj = packInfo.Deserialize(messageType);
- await Scene.MessageDispatcherComponent.RouteMessageHandler(session, messageType, entity, (IMessage)obj, packInfo.RpcId);
+ await Scene.MessageDispatcherComponent.RouteMessageHandler(session, messageType, entity, (IMessage)obj, packInfo.RpcId, packInfo.ProtocolCode);
}
return;
@@ -158,7 +159,7 @@ namespace Fantasy.Scheduler
case OpCodeType.OuterAddressableRequest:
case OpCodeType.OuterAddressableMessage:
{
- Scene.MessageDispatcherComponent.FailRouteResponse(session, messageType, InnerErrorCode.ErrNotFoundRoute, packInfo.RpcId);
+ Scene.MessageDispatcherComponent.FailRouteResponse(session, packInfo.ProtocolCode, InnerErrorCode.ErrNotFoundRoute, packInfo.RpcId);
return;
}
}
@@ -190,7 +191,7 @@ namespace Fantasy.Scheduler
}
var obj = packInfo.Deserialize(messageType);
- await Scene.MessageDispatcherComponent.RouteMessageHandler(session, messageType, entity, (IMessage)obj, packInfo.RpcId);
+ await Scene.MessageDispatcherComponent.RouteMessageHandler(session, messageType, entity, (IMessage)obj, packInfo.RpcId, packInfo.ProtocolCode);
}
return;
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/MessageHelper/NetworkMessagingComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/MessageHelper/NetworkMessagingComponent.cs
index 7580dd9..b176a4a 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/MessageHelper/NetworkMessagingComponent.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/MessageHelper/NetworkMessagingComponent.cs
@@ -71,7 +71,7 @@ namespace Fantasy.Scheduler
public readonly SortedDictionary RequestCallback = new();
public readonly Dictionary TimeoutRouteMessageSenders = new();
- public void SendInnerRoute(long routeId, IRouteMessage message)
+ public void SendInnerRoute(long routeId, T message) where T : IRouteMessage
{
if (routeId == 0)
{
@@ -93,7 +93,7 @@ namespace Fantasy.Scheduler
Scene.GetSession(routeId).Send(0, routeId, messageType, packInfo);
}
- public void SendInnerRoute(ICollection routeIdCollection, IRouteMessage message)
+ public void SendInnerRoute(ICollection routeIdCollection, T message) where T : IRouteMessage
{
if (routeIdCollection.Count <= 0)
{
@@ -109,7 +109,7 @@ namespace Fantasy.Scheduler
}
}
- public async FTask SendAddressable(long addressableId, IRouteMessage message)
+ public async FTask SendAddressable(long addressableId, T message) where T : IRouteMessage
{
await CallAddressable(addressableId, message);
}
@@ -121,7 +121,7 @@ namespace Fantasy.Scheduler
Log.Error($"CallInnerRoute routeId == 0");
return null;
}
-
+
var rpcId = ++_rpcId;
var session = Scene.GetSession(routeId);
var requestCallback = FTask.Create(false);
@@ -130,7 +130,7 @@ namespace Fantasy.Scheduler
return await requestCallback;
}
- public async FTask CallInnerRouteBySession(Session session, long routeId, IRouteMessage request)
+ public async FTask CallInnerRouteBySession(Session session, long routeId, T request) where T : IRouteMessage
{
var rpcId = ++_rpcId;
var requestCallback = FTask.Create(false);
@@ -139,7 +139,7 @@ namespace Fantasy.Scheduler
return await requestCallback;
}
- public async FTask CallInnerRoute(long routeId, IRouteMessage request)
+ public async FTask CallInnerRoute(long routeId, T request) where T : IRouteMessage
{
if (routeId == 0)
{
@@ -151,11 +151,11 @@ namespace Fantasy.Scheduler
var session = Scene.GetSession(routeId);
var requestCallback = FTask.Create(false);
RequestCallback.Add(rpcId, MessageSender.Create(rpcId, request, requestCallback));
- session.Send(request, rpcId, routeId);
+ session.Send(request, rpcId, routeId);
return await requestCallback;
}
- public async FTask CallAddressable(long addressableId, IRouteMessage request)
+ public async FTask CallAddressable(long addressableId, T request) where T : IRouteMessage
{
var failCount = 0;
@@ -172,7 +172,7 @@ namespace Fantasy.Scheduler
if (addressableRouteId == 0)
{
- return MessageDispatcherComponent.CreateResponse(request.GetType(), InnerErrorCode.ErrNotFoundRoute);
+ return MessageDispatcherComponent.CreateResponse(request.OpCode(), InnerErrorCode.ErrNotFoundRoute);
}
var iRouteResponse = await CallInnerRoute(addressableRouteId, request);
@@ -246,8 +246,8 @@ namespace Fantasy.Scheduler
}
case IRequest iRequest:
{
- var response = MessageDispatcherComponent.CreateResponse(iRequest.GetType(), InnerErrorCode.ErrRpcFail);
var responseRpcId = messageSender.RpcId;
+ var response = MessageDispatcherComponent.CreateResponse(iRequest.OpCode(), InnerErrorCode.ErrRpcFail);
ResponseHandler(responseRpcId, response);
Log.Warning($"timeout rpcId:{rpcId} responseRpcId:{responseRpcId} {iRequest.ToJson()}");
break;
@@ -256,7 +256,7 @@ namespace Fantasy.Scheduler
{
Log.Error(messageSender.Request != null
? $"Unsupported protocol type {messageSender.Request.GetType()} rpcId:{rpcId} messageSender.Request != null"
- : $"Unsupported protocol type:{messageSender.MessageType.FullName} rpcId:{rpcId}");
+ : $"Unsupported protocol type:{messageSender.MessageType} rpcId:{rpcId}");
RequestCallback.Remove(rpcId);
break;
}
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/OuterMessageScheduler.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/OuterMessageScheduler.cs
index 2c963ff..b7a95f2 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/OuterMessageScheduler.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Message/Scheduler/OuterMessageScheduler.cs
@@ -10,6 +10,7 @@ using Fantasy.PacketParser;
using Fantasy.Helper;
using Fantasy.InnerMessage;
using Fantasy.Roaming;
+#pragma warning disable CS8604 // Possible null reference argument.
#endif
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
@@ -125,7 +126,7 @@ namespace Fantasy.Scheduler
{
throw new Exception("OuterMessageScheduler error session does not have an AddressableRouteComponent component");
}
-
+
await addressableRouteComponent.Send(messageType, packInfo);
}
finally
@@ -164,7 +165,8 @@ namespace Fantasy.Scheduler
// session可能已经断开了,所以这里需要判断
if (session.RuntimeId == runtimeId)
{
- session.Send(response, rpcId);
+ var responseType = MessageDispatcherComponent.GetOpCodeType(response.OpCode());
+ session.Send(response, responseType, rpcId);
}
}
finally
@@ -184,7 +186,9 @@ namespace Fantasy.Scheduler
try
{
- if (!MessageDispatcherComponent.GetCustomRouteType(packInfoProtocolCode, out var routeType))
+ var routeType = MessageDispatcherComponent.GetCustomRouteType(packInfoProtocolCode);
+
+ if (!routeType.HasValue)
{
throw new Exception($"OuterMessageScheduler error 可能遭受到恶意发包或没有协议定义ProtocolCode ProtocolCode:{packInfo.ProtocolCode}");
}
@@ -203,7 +207,7 @@ namespace Fantasy.Scheduler
throw new Exception($"OuterMessageScheduler CustomRouteType session does not have an routeComponent component messageType:{messageType.FullName} ProtocolCode:{packInfo.ProtocolCode}");
}
- if (!routeComponent.TryGetRouteId(routeType, out var routeId))
+ if (!routeComponent.TryGetRouteId(routeType.Value, out var routeId))
{
throw new Exception($"OuterMessageScheduler RouteComponent cannot find RouteId with RouteType {routeType}");
}
@@ -227,7 +231,9 @@ namespace Fantasy.Scheduler
try
{
- if (!MessageDispatcherComponent.GetCustomRouteType(packInfoProtocolCode, out var routeType))
+ var routeType = MessageDispatcherComponent.GetCustomRouteType(packInfoProtocolCode);
+
+ if (!routeType.HasValue)
{
throw new Exception($"OuterMessageScheduler error 可能遭受到恶意发包或没有协议定义ProtocolCode ProtocolCode:{packInfo.ProtocolCode}");
}
@@ -246,7 +252,7 @@ namespace Fantasy.Scheduler
throw new Exception("OuterMessageScheduler CustomRouteType session does not have an routeComponent component");
}
- if (!routeComponent.TryGetRouteId(routeType, out var routeId))
+ if (!routeComponent.TryGetRouteId(routeType.Value, out var routeId))
{
throw new Exception($"OuterMessageScheduler RouteComponent cannot find RouteId with RouteType {routeType}");
}
@@ -257,7 +263,8 @@ namespace Fantasy.Scheduler
// session可能已经断开了,所以这里需要判断
if (session.RuntimeId == runtimeId)
{
- session.Send(response, rpcId);
+ var responseType = MessageDispatcherComponent.GetOpCodeType(response.OpCode());
+ session.Send(response, responseType, rpcId);
}
}
finally
@@ -277,7 +284,9 @@ namespace Fantasy.Scheduler
try
{
- if (!MessageDispatcherComponent.GetCustomRouteType(packInfoProtocolCode, out var routeType))
+ var routeType = MessageDispatcherComponent.GetCustomRouteType(packInfoProtocolCode);
+
+ if (!routeType.HasValue)
{
throw new Exception($"OuterMessageScheduler error 可能遭受到恶意发包或没有协议定义ProtocolCode ProtocolCode:{packInfo.ProtocolCode}");
}
@@ -296,7 +305,7 @@ namespace Fantasy.Scheduler
throw new Exception($"OuterMessageScheduler Roaming session does not have an sessionRoamingComponent component messageType:{messageType.FullName} ProtocolCode:{packInfo.ProtocolCode}");
}
- await sessionRoamingComponent.Send(routeType, messageType, packInfo);
+ await sessionRoamingComponent.Send(routeType.Value, messageType, packInfo);
}
finally
{
@@ -315,7 +324,9 @@ namespace Fantasy.Scheduler
try
{
- if (!MessageDispatcherComponent.GetCustomRouteType(packInfoProtocolCode, out var routeType))
+ var routeType = MessageDispatcherComponent.GetCustomRouteType(packInfoProtocolCode);
+
+ if (!routeType.HasValue)
{
throw new Exception($"OuterMessageScheduler error 可能遭受到恶意发包或没有协议定义ProtocolCode ProtocolCode:{packInfo.ProtocolCode}");
}
@@ -336,11 +347,12 @@ namespace Fantasy.Scheduler
var rpcId = packInfo.RpcId;
var runtimeId = session.RuntimeId;
- var response = await sessionRoamingComponent.Call(routeType, messageType, packInfo);
+ var response = await sessionRoamingComponent.Call(routeType.Value, messageType, packInfo);
// session可能已经断开了,所以这里需要判断
if (session.RuntimeId == runtimeId)
{
- session.Send(response, rpcId);
+ var responseType = MessageDispatcherComponent.GetOpCodeType(response.OpCode());
+ session.Send(response, responseType, rpcId);
}
}
finally
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/HTTP/HTTPServerNetwork.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/HTTP/HTTPServerNetwork.cs
index b3806fa..98a3aca 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/HTTP/HTTPServerNetwork.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/HTTP/HTTPServerNetwork.cs
@@ -67,19 +67,18 @@ namespace Fantasy.Network.HTTP
// 注册控制器服务
var addControllers = builder.Services.AddControllers()
.AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = null; });
- foreach (var assembly in AssemblySystem.ForEachAssembly)
+ foreach (var assemblyManifest in AssemblyManifest.GetAssemblyManifest)
{
- addControllers.AddApplicationPart(assembly);
+ addControllers.AddApplicationPart(assemblyManifest.Assembly);
}
var app = builder.Build();
- var listenUrl = $"http://{bindIp}:{port}/";;
+ var listenUrl = $"http://{bindIp}:{port}/";
app.Urls.Add(listenUrl);
// 启用开发者工具
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
-
// 路由注册
app.MapControllers();
// 开启监听
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/AClientNetwork.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/AClientNetwork.cs
index 322c811..7556ff1 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/AClientNetwork.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/AClientNetwork.cs
@@ -17,7 +17,7 @@ namespace Fantasy.Network.Interface
protected bool IsInit;
public Session Session { get; protected set; }
public abstract Session Connect(string remoteAddress, Action onConnectComplete, Action onConnectFail, Action onConnectDisconnect, bool isHttps, int connectTimeout = 5000);
- public abstract void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message);
+ public abstract void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType);
public override void Dispose()
{
IsInit = false;
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/ANetworkServerChannel.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/ANetworkServerChannel.cs
index 788a235..1e1bda4 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/ANetworkServerChannel.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/ANetworkServerChannel.cs
@@ -49,7 +49,7 @@ namespace Fantasy.Network.Interface
}
}
- public abstract void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message);
+ public abstract void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType);
}
}
#endif
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/INetworkChannel.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/INetworkChannel.cs
index 52f341a..2d7e727 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/INetworkChannel.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/Interface/INetworkChannel.cs
@@ -9,6 +9,6 @@ namespace Fantasy.Network.Interface
{
public Session Session { get;}
public bool IsDisposed { get;}
- public void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message);
+ public void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType);
}
}
\ No newline at end of file
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/KCP/Client/KCPClientNetwork.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/KCP/Client/KCPClientNetwork.cs
index f0f8868..ab45e49 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/KCP/Client/KCPClientNetwork.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/KCP/Client/KCPClientNetwork.cs
@@ -520,14 +520,14 @@ namespace Fantasy.Network.KCP
private const byte KcpHeaderRequestConnection = (byte)KcpHeader.RequestConnection;
private const byte KcpHeaderConfirmConnection = (byte)KcpHeader.ConfirmConnection;
- public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
if (_cancellationTokenSource.IsCancellationRequested)
{
return;
}
-
- var buffer = _packetParser.Pack(ref rpcId, ref routeId, memoryStream, message);
+
+ var buffer = _packetParser.Pack(ref rpcId, ref routeId, memoryStream, message, messageType);
if (!_isConnected)
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/KCP/Server/KCPServerNetworkChannel.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/KCP/Server/KCPServerNetworkChannel.cs
index 4216fa7..ff85d94 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/KCP/Server/KCPServerNetworkChannel.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/KCP/Server/KCPServerNetworkChannel.cs
@@ -105,7 +105,7 @@ namespace Fantasy.Network.KCP
}
}
- public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
if (IsDisposed)
{
@@ -120,7 +120,7 @@ namespace Fantasy.Network.KCP
return;
}
- var buffer = _packetParser.Pack(ref rpcId, ref routeId, memoryStream, message);
+ var buffer = _packetParser.Pack(ref rpcId, ref routeId, memoryStream, message, messageType);
Kcp.Send(buffer.GetBuffer().AsSpan(0, (int)buffer.Position));
if (buffer.MemoryStreamBufferSource == MemoryStreamBufferSource.Pack)
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/TCP/Client/TCPClientNetwork.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/TCP/Client/TCPClientNetwork.cs
index 233fb7b..3a1df5b 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/TCP/Client/TCPClientNetwork.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/TCP/Client/TCPClientNetwork.cs
@@ -316,9 +316,9 @@ namespace Fantasy.Network.TCP
#region Send
- public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- _sendBuffers.Enqueue(_packetParser.Pack(ref rpcId, ref routeId, memoryStream, message));
+ _sendBuffers.Enqueue(_packetParser.Pack(ref rpcId, ref routeId, memoryStream, message, messageType));
if (!_isSending)
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/TCP/Server/TCPServerNetworkChannel.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/TCP/Server/TCPServerNetworkChannel.cs
index 15f3f66..654f41a 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/TCP/Server/TCPServerNetworkChannel.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/TCP/Server/TCPServerNetworkChannel.cs
@@ -211,9 +211,9 @@ namespace Fantasy.Network.TCP
#region Send
- public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- _sendBuffers.Enqueue(_packetParser.Pack(ref rpcId, ref routeId, memoryStream, message));
+ _sendBuffers.Enqueue(_packetParser.Pack(ref rpcId, ref routeId, memoryStream, message, messageType));
if (!_isSending)
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Client/WebSocketClientNetwork.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Client/WebSocketClientNetwork.cs
index ef0b78f..d6f189f 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Client/WebSocketClientNetwork.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Client/WebSocketClientNetwork.cs
@@ -289,9 +289,9 @@ namespace Fantasy.Network.WebSocket
#region Send
- public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- _sendBuffers.Enqueue(_packetParser.Pack(ref rpcId, ref routeId, memoryStream, message));
+ _sendBuffers.Enqueue(_packetParser.Pack(ref rpcId, ref routeId, memoryStream, message, messageType));
if (!_isSending)
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Client/WebSocketClientNetworkWebgl.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Client/WebSocketClientNetworkWebgl.cs
index 36ef84d..c0c5713 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Client/WebSocketClientNetworkWebgl.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Client/WebSocketClientNetworkWebgl.cs
@@ -140,14 +140,14 @@ namespace Fantasy.Network.WebSocket
#region Send
- public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
if (IsDisposed)
{
return;
}
-
- var buffer = _packetParser.Pack(ref rpcId, ref routeId, memoryStream, message);
+
+ var buffer = _packetParser.Pack(ref rpcId, ref routeId, memoryStream, message, messageType);
if (!_isConnected)
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Server/WebSocketServerNetworkChannel.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Server/WebSocketServerNetworkChannel.cs
index 040745f..ae13ce9 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Server/WebSocketServerNetworkChannel.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Protocol/WebSocket/Server/WebSocketServerNetworkChannel.cs
@@ -230,9 +230,9 @@ public sealed class WebSocketServerNetworkChannel : ANetworkServerChannel
#region Send
- public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message)
+ public override void Send(uint rpcId, long routeId, MemoryStreamBuffer memoryStream, IMessage message, Type messageType)
{
- _sendBuffers.Enqueue(_packetParser.Pack(ref rpcId, ref routeId, memoryStream, message));
+ _sendBuffers.Enqueue(_packetParser.Pack(ref rpcId, ref routeId, memoryStream, message, messageType));
if (!_isSending)
{
diff --git a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Roaming/Component/SessionRoamingComponent.cs b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Roaming/Component/SessionRoamingComponent.cs
index 6834834..d295b60 100644
--- a/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Roaming/Component/SessionRoamingComponent.cs
+++ b/Fantasy/Fantasy.Net/Fantasy.Net/Runtime/Core/Network/Roaming/Component/SessionRoamingComponent.cs
@@ -190,7 +190,7 @@ public sealed class SessionRoamingComponent : Entity
/// 发送一个消息给漫游终
///
///
- public void Send(IRoamingMessage message)
+ public void Send(T message) where T : IRoamingMessage
{
Call(message.RouteType, message).Coroutine();
}
@@ -200,7 +200,7 @@ public sealed class SessionRoamingComponent : Entity
///
///
///
- public void Send(int roamingType, IRouteMessage message)
+ public void Send(int roamingType, T message) where T : IRouteMessage
{
Call(roamingType, message).Coroutine();
}
@@ -210,7 +210,7 @@ public sealed class SessionRoamingComponent : Entity
///
///
///
- public async FTask Call(IRoamingMessage message)
+ public async FTask Call(T message) where T : IRoamingMessage
{
return await Call(message.RouteType, message);
}
@@ -221,17 +221,16 @@ public sealed class SessionRoamingComponent : Entity
///