饭太稀
This commit is contained in:
101
Fantasy/Fantays.Console/Runtime/Core/Platform/Console/Entry.cs
Normal file
101
Fantasy/Fantays.Console/Runtime/Core/Platform/Console/Entry.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
#if FANTASY_CONSOLE
|
||||
using Fantasy.Assembly;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Serialize;
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
namespace Fantasy.Platform.Console
|
||||
{
|
||||
public struct OnFantasyInit
|
||||
{
|
||||
public Scene Scene;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 一般的控制台启动入口,可以适用大部分客户端环境
|
||||
/// </summary>
|
||||
public sealed class Entry
|
||||
{
|
||||
private static bool _isInit;
|
||||
private static Thread _updateThread;
|
||||
public static Scene Scene { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化框架
|
||||
/// </summary>
|
||||
/// <param name="assemblies"></param>
|
||||
public static async FTask Initialize(params System.Reflection.Assembly[] assemblies)
|
||||
{
|
||||
if (_isInit)
|
||||
{
|
||||
Log.Error("Fantasy has already been initialized and does not need to be initialized again!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化程序集管理系统
|
||||
await AssemblySystem.InnerInitialize(assemblies);
|
||||
// 初始化序列化
|
||||
SerializerManager.Initialize();
|
||||
_isInit = true;
|
||||
Log.Debug("Fantasy Initialize Complete!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动框架。
|
||||
/// 如果您的平台有每帧更新逻辑的方法,请不要调用这个方法。
|
||||
/// 如果没有实现每帧执行方法平台需要调用这个方法,目的是开启一个新的线程来每帧执行Update。
|
||||
/// 注意因为开启了一个新的线程来处理更新逻辑,所以要注意多线程的问题。
|
||||
/// </summary>
|
||||
public static void StartUpdate()
|
||||
{
|
||||
_updateThread = new Thread(() =>
|
||||
{
|
||||
while (_isInit)
|
||||
{
|
||||
ThreadScheduler.Update();
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
_updateThread.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在Entry中创建一个Scene,如果Scene已经被创建过,将先销毁Scene再创建。
|
||||
/// </summary>
|
||||
/// <param name="sceneRuntimeMode"></param>
|
||||
/// <returns></returns>
|
||||
public static async FTask<Scene> CreateScene(string sceneRuntimeMode = SceneRuntimeMode.MainThread)
|
||||
{
|
||||
Scene?.Dispose();
|
||||
Scene = await Scene.Create(sceneRuntimeMode);
|
||||
await Scene.EventComponent.PublishAsync(new OnFantasyInit()
|
||||
{
|
||||
Scene = Scene
|
||||
});
|
||||
return Scene;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果有的话一定要在每帧执行这个方法
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
ThreadScheduler.Update();
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
AssemblySystem.Dispose();
|
||||
SerializerManager.Dispose();
|
||||
Scene?.Dispose();
|
||||
Scene = null;
|
||||
_isInit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
#if FANTASY_CONSOLE
|
||||
#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 declaring as nullable.
|
||||
#pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
|
||||
namespace Fantasy
|
||||
{
|
||||
public sealed class ThreadSynchronizationContext : SynchronizationContext
|
||||
{
|
||||
private Action _actionHandler;
|
||||
private readonly Queue<Action> _queue = new();
|
||||
|
||||
public void Update()
|
||||
{
|
||||
while (_queue.TryDequeue(out _actionHandler))
|
||||
{
|
||||
try
|
||||
{
|
||||
_actionHandler();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Post(SendOrPostCallback callback, object state)
|
||||
{
|
||||
Post(() => callback(state));
|
||||
}
|
||||
|
||||
public void Post(Action action)
|
||||
{
|
||||
_queue.Enqueue(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
#if FANTASY_NET
|
||||
// ReSharper disable InconsistentNaming
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.Serialization;
|
||||
using Fantasy.Helper;
|
||||
using Newtonsoft.Json;
|
||||
#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 declaring as nullable.
|
||||
namespace Fantasy.Platform.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于记录服务器物理信息
|
||||
/// </summary>
|
||||
public sealed class MachineConfigData
|
||||
{
|
||||
/// <summary>
|
||||
/// 存放所有MachineConfigInfo信息
|
||||
/// </summary>
|
||||
public List<MachineConfig> List;
|
||||
[JsonIgnore]
|
||||
[IgnoreDataMember]
|
||||
private readonly ConcurrentDictionary<uint, MachineConfig> _configs = new ConcurrentDictionary<uint, MachineConfig>();
|
||||
/// <summary>
|
||||
/// 获得MachineConfig的实例
|
||||
/// </summary>
|
||||
public static MachineConfigData Instance { get; private set; }
|
||||
/// <summary>
|
||||
/// 初始化MachineConfig
|
||||
/// </summary>
|
||||
/// <param name="machineConfigJson"></param>
|
||||
public static void Initialize(string machineConfigJson)
|
||||
{
|
||||
Instance = machineConfigJson.Deserialize<MachineConfigData>();
|
||||
foreach (var config in Instance.List)
|
||||
{
|
||||
Instance._configs.TryAdd(config.Id, config);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据Id获取MachineConfig
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="FileNotFoundException"></exception>
|
||||
public MachineConfig Get(uint id)
|
||||
{
|
||||
if (_configs.TryGetValue(id, out var machineConfigInfo))
|
||||
{
|
||||
return machineConfigInfo;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException($"MachineConfig not find {id} Id");
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据Id获取MachineConfig
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGet(uint id, out MachineConfig config)
|
||||
{
|
||||
return _configs.TryGetValue(id, out config);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 表示一个物理服务器的信息
|
||||
/// </summary>
|
||||
public sealed class MachineConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public uint Id { get; set; }
|
||||
/// <summary>
|
||||
/// 外网IP
|
||||
/// </summary>
|
||||
public string OuterIP { get; set; }
|
||||
/// <summary>
|
||||
/// 外网绑定IP
|
||||
/// </summary>
|
||||
public string OuterBindIP { get; set; }
|
||||
/// <summary>
|
||||
/// 内网绑定IP
|
||||
/// </summary>
|
||||
public string InnerBindIP { get; set; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,100 @@
|
||||
#if FANTASY_NET
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.Serialization;
|
||||
using Fantasy.Helper;
|
||||
using Newtonsoft.Json;
|
||||
// ReSharper disable CollectionNeverUpdated.Global
|
||||
#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 declaring as nullable.
|
||||
|
||||
namespace Fantasy.Platform.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于管理进程信息
|
||||
/// </summary>
|
||||
public sealed class ProcessConfigData
|
||||
{
|
||||
/// <summary>
|
||||
/// 存放所有ProcessConfig信息
|
||||
/// </summary>
|
||||
public List<ProcessConfig> List;
|
||||
[JsonIgnore]
|
||||
[IgnoreDataMember]
|
||||
private readonly ConcurrentDictionary<uint, ProcessConfig> _configs = new ConcurrentDictionary<uint, ProcessConfig>();
|
||||
/// <summary>
|
||||
/// 获得ProcessConfigData的实例
|
||||
/// </summary>
|
||||
public static ProcessConfigData Instance { get; private set; }
|
||||
/// <summary>
|
||||
/// 初始化MachineConfig
|
||||
/// </summary>
|
||||
/// <param name="processConfigJson"></param>
|
||||
public static void Initialize(string processConfigJson)
|
||||
{
|
||||
Instance = processConfigJson.Deserialize<ProcessConfigData>();
|
||||
foreach (var config in Instance.List)
|
||||
{
|
||||
Instance._configs.TryAdd(config.Id, config);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据Id获取ProcessConfig
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="FileNotFoundException"></exception>
|
||||
public ProcessConfig Get(uint id)
|
||||
{
|
||||
if (_configs.TryGetValue(id, out var processConfigInfo))
|
||||
{
|
||||
return processConfigInfo;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException($"MachineConfig not find {id} Id");
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据Id获取ProcessConfig
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGet(uint id, out ProcessConfig config)
|
||||
{
|
||||
return _configs.TryGetValue(id, out config);
|
||||
}
|
||||
/// <summary>
|
||||
/// 按照startupGroup寻找属于startupGroup组的ProcessConfig
|
||||
/// </summary>
|
||||
/// <param name="startupGroup">startupGroup</param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<ProcessConfig> ForEachByStartupGroup(uint startupGroup)
|
||||
{
|
||||
foreach (var processConfig in List)
|
||||
{
|
||||
if (processConfig.StartupGroup == startupGroup)
|
||||
{
|
||||
yield return processConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 表示一个进程配置信息
|
||||
/// </summary>
|
||||
public sealed class ProcessConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程Id
|
||||
/// </summary>
|
||||
public uint Id { get; set; }
|
||||
/// <summary>
|
||||
/// 机器ID
|
||||
/// </summary>
|
||||
public uint MachineId { get; set; }
|
||||
/// <summary>
|
||||
/// 启动组
|
||||
/// </summary>
|
||||
public uint StartupGroup { get; set; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,196 @@
|
||||
#if FANTASY_NET
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.Serialization;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.DataStructure.Dictionary;
|
||||
using Fantasy.Helper;
|
||||
using Fantasy.IdFactory;
|
||||
using Newtonsoft.Json;
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
#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 declaring as nullable.
|
||||
namespace Fantasy.Platform.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// 存放所有SceneConfigInfo信息
|
||||
/// </summary>
|
||||
public sealed class SceneConfigData
|
||||
{
|
||||
/// <summary>
|
||||
/// 存放所有SceneConfig信息
|
||||
/// </summary>
|
||||
public List<SceneConfig> List;
|
||||
[JsonIgnore]
|
||||
[IgnoreDataMember]
|
||||
private readonly ConcurrentDictionary<uint, SceneConfig> _configs = new ConcurrentDictionary<uint, SceneConfig>();
|
||||
[JsonIgnore]
|
||||
[IgnoreDataMember]
|
||||
private readonly OneToManyList<int, SceneConfig> _sceneConfigBySceneType = new OneToManyList<int, SceneConfig>();
|
||||
[JsonIgnore]
|
||||
[IgnoreDataMember]
|
||||
private readonly OneToManyList<uint, SceneConfig> _sceneConfigByProcess = new OneToManyList<uint, SceneConfig>();
|
||||
[JsonIgnore] [IgnoreDataMember]
|
||||
private readonly Dictionary<int, Dictionary<int, List<SceneConfig>>> _worldSceneTypes = new Dictionary<int, Dictionary<int, List<SceneConfig>>>();
|
||||
/// <summary>
|
||||
/// 获得SceneConfigData的实例
|
||||
/// </summary>
|
||||
public static SceneConfigData Instance { get; private set; }
|
||||
/// <summary>
|
||||
/// 初始化SceneConfig
|
||||
/// </summary>
|
||||
/// <param name="sceneConfigJson"></param>
|
||||
public static void Initialize(string sceneConfigJson)
|
||||
{
|
||||
Instance = sceneConfigJson.Deserialize<SceneConfigData>();
|
||||
foreach (var config in Instance.List)
|
||||
{
|
||||
config.Initialize();
|
||||
Instance._configs.TryAdd(config.Id, config);
|
||||
Instance._sceneConfigByProcess.Add(config.ProcessConfigId, config);
|
||||
Instance._sceneConfigBySceneType.Add(config.SceneType, config);
|
||||
|
||||
var configWorldConfigId = (int)config.WorldConfigId;
|
||||
|
||||
if (!Instance._worldSceneTypes.TryGetValue(configWorldConfigId, out var sceneConfigDic))
|
||||
{
|
||||
sceneConfigDic = new Dictionary<int, List<SceneConfig>>();
|
||||
Instance._worldSceneTypes.Add(configWorldConfigId, sceneConfigDic);
|
||||
}
|
||||
|
||||
if (!sceneConfigDic.TryGetValue(config.SceneType, out var sceneConfigList))
|
||||
{
|
||||
sceneConfigList = new List<SceneConfig>();
|
||||
sceneConfigDic.Add(config.SceneType, sceneConfigList);
|
||||
}
|
||||
|
||||
sceneConfigList.Add(config);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据Id获取SceneConfig
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="FileNotFoundException"></exception>
|
||||
public SceneConfig Get(uint id)
|
||||
{
|
||||
if (_configs.TryGetValue(id, out var sceneConfigInfo))
|
||||
{
|
||||
return sceneConfigInfo;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException($"WorldConfig not find {id} Id");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据Id获取SceneConfig
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGet(uint id, out SceneConfig config)
|
||||
{
|
||||
return _configs.TryGetValue(id, out config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得SceneConfig
|
||||
/// </summary>
|
||||
/// <param name="serverConfigId"></param>
|
||||
/// <returns></returns>
|
||||
public List<SceneConfig> GetByProcess(uint serverConfigId)
|
||||
{
|
||||
return _sceneConfigByProcess.TryGetValue(serverConfigId, out var list) ? list : new List<SceneConfig>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得SceneConfig
|
||||
/// </summary>
|
||||
/// <param name="sceneType"></param>
|
||||
/// <returns></returns>
|
||||
public List<SceneConfig> GetSceneBySceneType(int sceneType)
|
||||
{
|
||||
return !_sceneConfigBySceneType.TryGetValue(sceneType, out var list) ? new List<SceneConfig>() : list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得SceneConfig
|
||||
/// </summary>
|
||||
/// <param name="world"></param>
|
||||
/// <param name="sceneType"></param>
|
||||
/// <returns></returns>
|
||||
public List<SceneConfig> GetSceneBySceneType(int world, int sceneType)
|
||||
{
|
||||
if (!_worldSceneTypes.TryGetValue(world, out var sceneConfigDic))
|
||||
{
|
||||
return new List<SceneConfig>();
|
||||
}
|
||||
|
||||
if (!sceneConfigDic.TryGetValue(sceneType, out var list))
|
||||
{
|
||||
return new List<SceneConfig>();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个Scene配置信息
|
||||
/// </summary>
|
||||
public sealed class SceneConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public uint Id { get; set; }
|
||||
/// <summary>
|
||||
/// 进程Id
|
||||
/// </summary>
|
||||
public uint ProcessConfigId { get; set; }
|
||||
/// <summary>
|
||||
/// 世界Id
|
||||
/// </summary>
|
||||
public uint WorldConfigId { get; set; }
|
||||
/// <summary>
|
||||
/// Scene运行类型
|
||||
/// </summary>
|
||||
public string SceneRuntimeMode { get; set; }
|
||||
/// <summary>
|
||||
/// Scene类型
|
||||
/// </summary>
|
||||
public string SceneTypeString { get; set; }
|
||||
/// <summary>
|
||||
/// 协议类型
|
||||
/// </summary>
|
||||
public string NetworkProtocol { get; set; }
|
||||
/// <summary>
|
||||
/// 外网端口
|
||||
/// </summary>
|
||||
public int OuterPort { get; set; }
|
||||
/// <summary>
|
||||
/// 内网端口
|
||||
/// </summary>
|
||||
public int InnerPort { get; set; }
|
||||
/// <summary>
|
||||
/// Scene类型
|
||||
/// </summary>
|
||||
public int SceneType { get; set; }
|
||||
/// <summary>
|
||||
/// RouteId
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[IgnoreDataMember]
|
||||
public long RouteId { get; private set; }
|
||||
/// <summary>
|
||||
/// 初始化方法
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
RouteId = IdFactoryHelper.RuntimeId(0, Id, (byte)WorldConfigId, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
#if FANTASY_NET
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.Serialization;
|
||||
using Fantasy.Helper;
|
||||
using Newtonsoft.Json;
|
||||
#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 declaring as nullable.
|
||||
namespace Fantasy.Platform.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// 存放所有WorldConfigInfo信息
|
||||
/// </summary>
|
||||
public sealed class WorldConfigData
|
||||
{
|
||||
/// <summary>
|
||||
/// 存放所有WorldConfigInfo信息
|
||||
/// </summary>
|
||||
public List<WorldConfig> List;
|
||||
[JsonIgnore]
|
||||
[IgnoreDataMember]
|
||||
private readonly ConcurrentDictionary<uint, WorldConfig> _configs = new ConcurrentDictionary<uint, WorldConfig>();
|
||||
/// <summary>
|
||||
/// 获得WorldConfig的实例
|
||||
/// </summary>
|
||||
public static WorldConfigData Instance { get; private set; }
|
||||
/// <summary>
|
||||
/// 初始化WorldConfig
|
||||
/// </summary>
|
||||
/// <param name="worldConfigJson"></param>
|
||||
public static void Initialize(string worldConfigJson)
|
||||
{
|
||||
Instance = worldConfigJson.Deserialize<WorldConfigData>();
|
||||
foreach (var config in Instance.List)
|
||||
{
|
||||
Instance._configs.TryAdd(config.Id, config);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据Id获取WorldConfig
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="FileNotFoundException"></exception>
|
||||
public WorldConfig Get(uint id)
|
||||
{
|
||||
if (_configs.TryGetValue(id, out var worldConfigInfo))
|
||||
{
|
||||
return worldConfigInfo;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException($"WorldConfig not find {id} Id");
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据Id获取WorldConfig
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGet(uint id, out WorldConfig config)
|
||||
{
|
||||
return _configs.TryGetValue(id, out config);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个世界配置信息
|
||||
/// </summary>
|
||||
public sealed class WorldConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public uint Id { get; set; }
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string WorldName { get; set; }
|
||||
/// <summary>
|
||||
/// 数据库连接字符串
|
||||
/// </summary>
|
||||
public string DbConnection { get; set; }
|
||||
/// <summary>
|
||||
/// 数据库名称
|
||||
/// </summary>
|
||||
public string DbName { get; set; }
|
||||
/// <summary>
|
||||
/// 数据库类型
|
||||
/// </summary>
|
||||
public string DbType { get; set; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
124
Fantasy/Fantays.Console/Runtime/Core/Platform/Net/Entry.cs
Normal file
124
Fantasy/Fantays.Console/Runtime/Core/Platform/Net/Entry.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
#if FANTASY_NET
|
||||
using CommandLine;
|
||||
using Fantasy.Assembly;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Helper;
|
||||
using Fantasy.IdFactory;
|
||||
using Fantasy.LowLevel;
|
||||
using Fantasy.Network;
|
||||
using Fantasy.Serialize;
|
||||
// ReSharper disable FunctionNeverReturns
|
||||
|
||||
namespace Fantasy.Platform.Net;
|
||||
|
||||
/// <summary>
|
||||
/// Fantasy.Net 应用程序入口
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">当命令行格式异常时抛出。</exception>
|
||||
/// <exception cref="NotSupportedException">不支持的 ProcessType 类型异常。</exception>
|
||||
public static class Entry
|
||||
{
|
||||
/// <summary>
|
||||
/// 框架初始化
|
||||
/// </summary>
|
||||
/// <param name="assemblies">注册的Assembly</param>
|
||||
public static async FTask Initialize(params System.Reflection.Assembly[] assemblies)
|
||||
{
|
||||
// 解析命令行参数
|
||||
Parser.Default.ParseArguments<CommandLineOptions>(Environment.GetCommandLineArgs())
|
||||
.WithNotParsed(error => throw new Exception("Command line format error!"))
|
||||
.WithParsed(option =>
|
||||
{
|
||||
ProcessDefine.Options = option;
|
||||
ProcessDefine.InnerNetwork = Enum.Parse<NetworkProtocolType>(option.InnerNetwork);
|
||||
});
|
||||
// 初始化Log系统
|
||||
Log.Initialize();
|
||||
// 检查启动参数,后期可能有机器人等不同的启动参数
|
||||
switch (ProcessDefine.Options.ProcessType)
|
||||
{
|
||||
case "Game":
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new NotSupportedException($"ProcessType is {ProcessDefine.Options.ProcessType} Unrecognized!");
|
||||
}
|
||||
}
|
||||
// 初始化程序集管理系统
|
||||
await AssemblySystem.InnerInitialize(assemblies);
|
||||
// 初始化序列化
|
||||
SerializerManager.Initialize();
|
||||
// 精度处理(只针对Windows下有作用、其他系统没有这个问题、一般也不会用Windows来做服务器的)
|
||||
WinPeriod.Initialize();
|
||||
|
||||
FantasyMemory.Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动Fantasy.Net
|
||||
/// </summary>
|
||||
public static async FTask Start()
|
||||
{
|
||||
// 启动Process
|
||||
StartProcess().Coroutine();
|
||||
await FTask.CompletedTask;
|
||||
while (true)
|
||||
{
|
||||
ThreadScheduler.Update();
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化并且启动框架
|
||||
/// </summary>
|
||||
/// <param name="assemblies"></param>
|
||||
public static async FTask Start(params System.Reflection.Assembly[] assemblies)
|
||||
{
|
||||
await Initialize(assemblies);
|
||||
await Start();
|
||||
}
|
||||
|
||||
private static async FTask StartProcess()
|
||||
{
|
||||
if (ProcessDefine.Options.StartupGroup != 0)
|
||||
{
|
||||
foreach (var processConfig in ProcessConfigData.Instance.ForEachByStartupGroup((uint)ProcessDefine.Options.StartupGroup))
|
||||
{
|
||||
await Process.Create(processConfig.Id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ProcessDefine.Options.Mode)
|
||||
{
|
||||
case "Develop":
|
||||
{
|
||||
foreach (var processConfig in ProcessConfigData.Instance.List)
|
||||
{
|
||||
await Process.Create(processConfig.Id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case "Release":
|
||||
{
|
||||
await Process.Create(ProcessDefine.Options.ProcessId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭 Fantasy
|
||||
/// </summary>
|
||||
public static void Close()
|
||||
{
|
||||
AssemblySystem.Dispose();
|
||||
SerializerManager.Dispose();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
156
Fantasy/Fantays.Console/Runtime/Core/Platform/Net/Process.cs
Normal file
156
Fantasy/Fantays.Console/Runtime/Core/Platform/Net/Process.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
#if FANTASY_NET
|
||||
using System.Collections.Concurrent;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.IdFactory;
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||
namespace Fantasy.Platform.Net;
|
||||
|
||||
/// <summary>
|
||||
/// 一个进程的实例
|
||||
/// </summary>
|
||||
public sealed class Process : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前进程的Id
|
||||
/// </summary>
|
||||
public readonly uint Id;
|
||||
/// <summary>
|
||||
/// 进程关联的MachineId
|
||||
/// </summary>
|
||||
public readonly uint MachineId;
|
||||
private readonly ConcurrentDictionary<uint, Scene> _processScenes = new ConcurrentDictionary<uint, Scene>();
|
||||
private static readonly ConcurrentDictionary<uint, Scene> Scenes = new ConcurrentDictionary<uint, Scene>();
|
||||
private Process() {}
|
||||
private Process(uint id, uint machineId)
|
||||
{
|
||||
Id = id;
|
||||
MachineId = machineId;
|
||||
}
|
||||
|
||||
internal bool IsProcess(ref long routeId)
|
||||
{
|
||||
var sceneId = IdFactoryHelper.RuntimeIdTool.GetSceneId(ref routeId);
|
||||
return _processScenes.ContainsKey(sceneId);
|
||||
}
|
||||
|
||||
internal bool IsProcess(ref uint sceneId)
|
||||
{
|
||||
return _processScenes.ContainsKey(sceneId);
|
||||
}
|
||||
|
||||
internal void AddSceneToProcess(Scene scene)
|
||||
{
|
||||
_processScenes.TryAdd(scene.SceneConfigId, scene);
|
||||
}
|
||||
|
||||
internal void RemoveSceneToProcess(Scene scene, bool isDispose)
|
||||
{
|
||||
if (!_processScenes.Remove(scene.SceneConfigId, out _))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDispose)
|
||||
{
|
||||
scene.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TryGetSceneToProcess(long routeId, out Scene scene)
|
||||
{
|
||||
var sceneId = IdFactoryHelper.RuntimeIdTool.GetSceneId(ref routeId);
|
||||
return _processScenes.TryGetValue(sceneId, out scene);
|
||||
}
|
||||
|
||||
internal bool TryGetSceneToProcess(uint sceneId, out Scene scene)
|
||||
{
|
||||
return _processScenes.TryGetValue(sceneId, out scene);
|
||||
}
|
||||
/// <summary>
|
||||
/// 销毁方法
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_processScenes.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var sceneQueue = new Queue<Scene>();
|
||||
|
||||
foreach (var (_, scene) in _processScenes)
|
||||
{
|
||||
sceneQueue.Enqueue(scene);
|
||||
}
|
||||
|
||||
while (sceneQueue.TryDequeue(out var removeScene))
|
||||
{
|
||||
removeScene.Dispose();
|
||||
}
|
||||
|
||||
_processScenes.Clear();
|
||||
}
|
||||
|
||||
internal static async FTask<Process?> Create(uint processConfigId)
|
||||
{
|
||||
if (!ProcessConfigData.Instance.TryGet(processConfigId, out var processConfig))
|
||||
{
|
||||
Log.Error($"not found processConfig by Id:{processConfigId}");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!MachineConfigData.Instance.TryGet(processConfig.MachineId, out var machineConfig))
|
||||
{
|
||||
Log.Error($"not found machineConfig by Id:{processConfig.MachineId}");
|
||||
return null;
|
||||
}
|
||||
|
||||
var process = new Process(processConfigId, processConfig.MachineId);
|
||||
var sceneConfigs = SceneConfigData.Instance.GetByProcess(processConfigId);
|
||||
|
||||
foreach (var sceneConfig in sceneConfigs)
|
||||
{
|
||||
await Scene.Create(process, machineConfig, sceneConfig);
|
||||
}
|
||||
|
||||
Log.Info($"Process:{processConfigId} Startup Complete SceneCount:{sceneConfigs.Count}");
|
||||
return process;
|
||||
}
|
||||
|
||||
internal bool IsInAppliaction(ref uint sceneId)
|
||||
{
|
||||
return _processScenes.ContainsKey(sceneId);
|
||||
}
|
||||
|
||||
internal static void AddScene(Scene scene)
|
||||
{
|
||||
Scenes.TryAdd(scene.SceneConfigId, scene);
|
||||
}
|
||||
|
||||
internal static void RemoveScene(Scene scene, bool isDispose)
|
||||
{
|
||||
if (!Scenes.Remove(scene.SceneConfigId, out _))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDispose)
|
||||
{
|
||||
scene.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool TryGetScene(long routeId, out Scene scene)
|
||||
{
|
||||
var sceneId = IdFactoryHelper.RuntimeIdTool.GetSceneId(ref routeId);
|
||||
return Scenes.TryGetValue(sceneId, out scene);
|
||||
}
|
||||
|
||||
internal static bool TryGetScene(uint sceneId, out Scene scene)
|
||||
{
|
||||
return Scenes.TryGetValue(sceneId, out scene);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,99 @@
|
||||
#if FANTASY_NET
|
||||
using CommandLine;
|
||||
using Fantasy.Network;
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
namespace Fantasy.Platform.Net;
|
||||
|
||||
/// <summary>
|
||||
/// Process运行模式
|
||||
/// </summary>
|
||||
public enum ProcessMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认
|
||||
/// </summary>
|
||||
None =0,
|
||||
/// <summary>
|
||||
/// 开发模式
|
||||
/// </summary>
|
||||
Develop = 1,
|
||||
/// <summary>
|
||||
/// 发布模式
|
||||
/// </summary>
|
||||
Release = 2
|
||||
}
|
||||
|
||||
internal sealed class CommandLineOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于启动指定的进程,该进程的 ID 与 ProcessConfig 的 ID 相关联。此参数只能传递单个 ID,不支持传递多个 ID。
|
||||
/// </summary>
|
||||
[Option("pid", Required = false, Default = (uint)0, HelpText = "Enter an ProcessIdId such as 1")]
|
||||
public uint ProcessId { get; set; }
|
||||
/// <summary>
|
||||
/// Process类型,获取或设置应用程序的类型。
|
||||
/// Game - 游戏服务器Process
|
||||
/// Robot - 机器人(暂未支持该功能)
|
||||
/// </summary>
|
||||
[Option('a', "ProcessType", Required = false, Default = "Game", HelpText = "Game")]
|
||||
public string ProcessType { get; set; }
|
||||
/// <summary>
|
||||
/// 服务器运行模式,获取或设置服务器的运行模式。
|
||||
/// Develop - 开发模式(启动Process配置表中的所有Process)
|
||||
/// Release - 发布模式(根据ProcessId启动Process)
|
||||
/// </summary>
|
||||
[Option('m', "Mode", Required = true, Default = "Release", HelpText = "Develop:启动Process配置表中的所有Process,\nRelease:根据ProcessId启动Process")]
|
||||
public string Mode { get; set; }
|
||||
/// <summary>
|
||||
/// 服务器内部网络协议
|
||||
/// TCP - 服务器内部之间通讯使用TCP协议
|
||||
/// KCP - 服务器内部之间通讯使用KCP协议
|
||||
/// WebSocket - 服务器内部之间通讯使用WebSocket协议(不推荐、TCP或KCP)
|
||||
/// </summary>
|
||||
[Option('n', "InnerNetwork", Required = false, Default = "TCP", HelpText = "TCP、KCP、WebSocket")]
|
||||
public string InnerNetwork { get; set; }
|
||||
/// <summary>
|
||||
/// 会话空闲检查超时时间。
|
||||
/// </summary>
|
||||
[Option('t', "SessionIdleCheckerTimeout", Required = false, Default = 8000, HelpText = "Session idle check timeout")]
|
||||
public int SessionIdleCheckerTimeout { get; set; }
|
||||
/// <summary>
|
||||
/// 会话空闲检查间隔。
|
||||
/// </summary>
|
||||
[Option('i', "SessionIdleCheckerInterval", Required = false, Default = 5000, HelpText = "Session idle check interval")]
|
||||
public int SessionIdleCheckerInterval { get; set; }
|
||||
/// <summary>
|
||||
/// 启动组。
|
||||
/// </summary>
|
||||
[Option('g', "StartupGroup", Required = false, Default = 0, HelpText = "Used to start a group of Process")]
|
||||
public int StartupGroup { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AppDefine
|
||||
/// </summary>
|
||||
internal static class ProcessDefine
|
||||
{
|
||||
/// <summary>
|
||||
/// 命令行选项
|
||||
/// </summary>
|
||||
public static CommandLineOptions Options;
|
||||
/// <summary>
|
||||
/// App程序Id
|
||||
/// </summary>
|
||||
public static uint ProcessId => Options.ProcessId;
|
||||
/// <summary>
|
||||
/// 会话空闲检查超时时间。
|
||||
/// </summary>
|
||||
public static int SessionIdleCheckerTimeout => Options.SessionIdleCheckerTimeout;
|
||||
/// <summary>
|
||||
/// 会话空闲检查间隔。
|
||||
/// </summary>
|
||||
public static int SessionIdleCheckerInterval => Options.SessionIdleCheckerInterval;
|
||||
/// <summary>
|
||||
/// 内部网络通讯协议类型
|
||||
/// </summary>
|
||||
public static NetworkProtocolType InnerNetwork;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
#if FANTASY_NET
|
||||
using System.Collections.Concurrent;
|
||||
#pragma warning disable CS8765
|
||||
#pragma warning disable CS8601
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
/// <summary>
|
||||
/// 线程的同步上下文
|
||||
/// </summary>
|
||||
public sealed class ThreadSynchronizationContext : SynchronizationContext
|
||||
{
|
||||
private readonly ConcurrentQueue<Action> _queue = new();
|
||||
/// <summary>
|
||||
/// 执行当前上下文投递过的逻辑
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
while (_queue.TryDequeue(out var actionHandler))
|
||||
{
|
||||
try
|
||||
{
|
||||
actionHandler();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 投递一个逻辑到当前上下文
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="state"></param>
|
||||
public override void Post(SendOrPostCallback callback, object state)
|
||||
{
|
||||
Post(() => callback(state));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 投递一个逻辑到当前上下文
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
public void Post(Action action)
|
||||
{
|
||||
_queue.Enqueue(action);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#if FANTASY_UNITY
|
||||
namespace Fantasy.Platform.Unity
|
||||
{
|
||||
public static class AppDefine
|
||||
{
|
||||
public static string RemoteUpdatePath;
|
||||
public static bool EditorModel = true;
|
||||
public const string VersionName = "version.bytes";
|
||||
public const string VersionMD5Name = "version.md5";
|
||||
public const string AssetBundleManifestName = "Fantasy";
|
||||
public static bool IsEditor => UnityEngine.Application.isEditor && EditorModel;
|
||||
public static string AssetBundleSaveDirectory => "Assets/AssetBundles";
|
||||
public static string LocalAssetBundlePath => UnityEngine.Application.streamingAssetsPath;
|
||||
public static string RemoteAssetBundlePath => UnityEngine.Application.persistentDataPath;
|
||||
public static string PersistentDataVersion => $"{UnityEngine.Application.persistentDataPath}/{VersionName}";
|
||||
public static string StreamingAssetsVersion => $"{UnityEngine.Application.streamingAssetsPath}/{VersionName}";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#if FANTASY_UNITY
|
||||
using System;
|
||||
namespace MongoDB.Bson.Serialization.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class BsonDefaultValueAttribute : Attribute
|
||||
{
|
||||
public BsonDefaultValueAttribute(object defaultValue) { }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
#if FANTASY_UNITY
|
||||
using System;
|
||||
namespace MongoDB.Bson.Serialization.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class BsonElementAttribute : Attribute
|
||||
{
|
||||
public BsonElementAttribute() { }
|
||||
|
||||
public BsonElementAttribute(string elementName) { }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#if FANTASY_UNITY
|
||||
using System;
|
||||
namespace MongoDB.Bson.Serialization.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class BsonIdAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#if FANTASY_UNITY
|
||||
using System;
|
||||
namespace MongoDB.Bson.Serialization.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class BsonIgnoreAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
#if FANTASY_UNITY
|
||||
using System;
|
||||
namespace MongoDB.Bson.Serialization.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class BsonIgnoreIfDefaultAttribute : Attribute
|
||||
{
|
||||
public BsonIgnoreIfDefaultAttribute() { }
|
||||
|
||||
public BsonIgnoreIfDefaultAttribute(bool value) { }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#if FANTASY_UNITY
|
||||
using System;
|
||||
namespace MongoDB.Bson.Serialization.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class BsonIgnoreIfNullAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
102
Fantasy/Fantays.Console/Runtime/Core/Platform/Unity/Entry.cs
Normal file
102
Fantasy/Fantays.Console/Runtime/Core/Platform/Unity/Entry.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
#if FANTASY_UNITY
|
||||
using System.Linq;
|
||||
using Fantasy.Assembly;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Serialize;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Scripting;
|
||||
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
|
||||
namespace Fantasy.Platform.Unity
|
||||
{
|
||||
public sealed class FantasyObject : MonoBehaviour
|
||||
{
|
||||
public static GameObject FantasyObjectGameObject { get; private set; }
|
||||
|
||||
public static void OnRuntimeMethodLoad()
|
||||
{
|
||||
FantasyObjectGameObject = new GameObject("Fantasy.Net");
|
||||
DontDestroyOnLoad(FantasyObjectGameObject);
|
||||
}
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
Destroy(FantasyObjectGameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public struct OnSceneCreate
|
||||
{
|
||||
public Scene Scene;
|
||||
public object Arg;
|
||||
}
|
||||
|
||||
public class Entry : MonoBehaviour
|
||||
{
|
||||
private static bool _isInit;
|
||||
public static Scene Scene { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化框架
|
||||
/// </summary>
|
||||
/// <param name="assemblies"></param>
|
||||
public static async FTask Initialize(params System.Reflection.Assembly[] assemblies)
|
||||
{
|
||||
if (_isInit)
|
||||
{
|
||||
Log.Error("Fantasy has already been initialized and does not need to be initialized again!");
|
||||
return;
|
||||
}
|
||||
FantasyObject.OnRuntimeMethodLoad();
|
||||
Log.Register(new UnityLog());
|
||||
await AssemblySystem.InnerInitialize(assemblies);
|
||||
// 初始化序列化
|
||||
SerializerManager.Initialize();
|
||||
#if FANTASY_WEBGL
|
||||
ThreadSynchronizationContext.Initialize();
|
||||
#endif
|
||||
_isInit = true;
|
||||
FantasyObject.FantasyObjectGameObject.AddComponent<Entry>();
|
||||
Log.Debug("Fantasy Initialize Complete!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在Entry中创建一个Scene,如果Scene已经被创建过,将先销毁Scene再创建。
|
||||
/// </summary>
|
||||
/// <param name="arg"></param>
|
||||
/// <param name="sceneRuntimeMode"></param>
|
||||
/// <returns></returns>
|
||||
public static async FTask<Scene> CreateScene(object arg = null, string sceneRuntimeMode = SceneRuntimeMode.MainThread)
|
||||
{
|
||||
Scene?.Dispose();
|
||||
Scene = await Scene.Create(sceneRuntimeMode);
|
||||
await Scene.EventComponent.PublishAsync(new OnSceneCreate()
|
||||
{
|
||||
Arg = arg,
|
||||
Scene = Scene
|
||||
});
|
||||
return Scene;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
ThreadScheduler.Update();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
AssemblySystem.Dispose();
|
||||
SerializerManager.Dispose();
|
||||
if (Scene != null)
|
||||
{
|
||||
Scene?.Dispose();
|
||||
Scene = null;
|
||||
}
|
||||
_isInit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
108
Fantasy/Fantays.Console/Runtime/Core/Platform/Unity/Temp.cs
Normal file
108
Fantasy/Fantays.Console/Runtime/Core/Platform/Unity/Temp.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
// using System.Reflection;
|
||||
// using Fantasy.Assembly;
|
||||
// using Fantasy.Async;
|
||||
// // using UnityEngine;
|
||||
// #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
|
||||
// #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
// #pragma warning disable CS8603 // Possible null reference return.
|
||||
// #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
// #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
//
|
||||
// namespace Fantasy.Platform.Unity
|
||||
// {
|
||||
// public class MonoBehaviour
|
||||
// {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public class GameObject
|
||||
// {
|
||||
// public GameObject(string name)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// internal enum RuntimeInitializeLoadType
|
||||
// {
|
||||
// BeforeSceneLoad = 1,
|
||||
// }
|
||||
//
|
||||
// internal class RuntimeInitializeOnLoadMethodAttribute : Attribute
|
||||
// {
|
||||
// public RuntimeInitializeLoadType RuntimeInitializeLoadType;
|
||||
//
|
||||
// public RuntimeInitializeOnLoadMethodAttribute(RuntimeInitializeLoadType loadType)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public sealed class FantasyObject : MonoBehaviour
|
||||
// {
|
||||
// public static GameObject FantasyObjectGameObject { get; private set; }
|
||||
// // 这个方法将在游戏启动时自动调用
|
||||
// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
// static void OnRuntimeMethodLoad()
|
||||
// {
|
||||
// FantasyObjectGameObject = new GameObject("Fantasy.Net");
|
||||
// // DontDestroyOnLoad(FantasyObjectGameObject);
|
||||
// }
|
||||
// private void OnApplicationQuit()
|
||||
// {
|
||||
// // Destroy(FantasyObjectGameObject);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public struct OnFantasyInit
|
||||
// {
|
||||
// public Scene Scene;
|
||||
// }
|
||||
//
|
||||
// public class Entry : MonoBehaviour
|
||||
// {
|
||||
// private static bool _isInit;
|
||||
// public static Scene Scene { get; private set; }
|
||||
// /// <summary>
|
||||
// /// 初始化框架
|
||||
// /// </summary>
|
||||
// public static async FTask<Scene> Initialize(params System.Reflection.Assembly[] assemblies)
|
||||
// {
|
||||
// Scene?.Dispose();
|
||||
// // 初始化程序集管理系统
|
||||
// AssemblySystem.Initialize(assemblies);
|
||||
// if (!_isInit)
|
||||
// {
|
||||
// #if FANTASY_WEBGL
|
||||
// ThreadSynchronizationContext.Initialize();
|
||||
// #endif
|
||||
// _isInit = true;
|
||||
// // FantasyObject.FantasyObjectGameObject.AddComponent<Entry>();
|
||||
// }
|
||||
// // Scene = await Scene.Create(SceneRuntimeType.MainThread);
|
||||
// // await Scene.EventComponent.PublishAsync(new OnFantasyInit()
|
||||
// // {
|
||||
// // Scene = Scene
|
||||
// // });
|
||||
// // return Scene;
|
||||
// await FTask.CompletedTask;
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// private void Update()
|
||||
// {
|
||||
// ThreadScheduler.Update();
|
||||
// }
|
||||
//
|
||||
// private void OnDestroy()
|
||||
// {
|
||||
// AssemblySystem.Dispose();
|
||||
// if (Scene != null)
|
||||
// {
|
||||
// Scene?.Dispose();
|
||||
// Scene = null;
|
||||
// }
|
||||
// _isInit = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,104 @@
|
||||
#if FANTASY_UNITY && !FANTASY_WEBGL
|
||||
#pragma warning disable CS8765
|
||||
#pragma warning disable CS8601
|
||||
#pragma warning disable CS8618
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace Fantasy
|
||||
{
|
||||
public sealed class ThreadSynchronizationContext : SynchronizationContext
|
||||
{
|
||||
private Action _actionHandler;
|
||||
private readonly ConcurrentQueue<Action> _queue = new();
|
||||
|
||||
public void Update()
|
||||
{
|
||||
while (_queue.TryDequeue(out _actionHandler))
|
||||
{
|
||||
try
|
||||
{
|
||||
_actionHandler();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Post(SendOrPostCallback callback, object state)
|
||||
{
|
||||
Post(() => callback(state));
|
||||
}
|
||||
|
||||
public void Post(Action action)
|
||||
{
|
||||
_queue.Enqueue(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if FANTASY_UNITY && FANTASY_WEBGL
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Fantasy;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
public class WebGLSynchronizationContextUpdater : MonoBehaviour
|
||||
{
|
||||
private ThreadSynchronizationContext _context;
|
||||
|
||||
public void Initialize(ThreadSynchronizationContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
_context.Update();
|
||||
}
|
||||
}
|
||||
public sealed class ThreadSynchronizationContext : SynchronizationContext
|
||||
{
|
||||
private Action _actionHandler;
|
||||
private readonly Queue<Action> _queue = new();
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
var context = new ThreadSynchronizationContext();
|
||||
SetSynchronizationContext(context);
|
||||
var go = new GameObject("WebGLSynchronizationContextUpdater");
|
||||
go.AddComponent<WebGLSynchronizationContextUpdater>().Initialize(context);
|
||||
Object.DontDestroyOnLoad(go);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
while (_queue.TryDequeue(out _actionHandler))
|
||||
{
|
||||
try
|
||||
{
|
||||
_actionHandler();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Post(SendOrPostCallback callback, object state)
|
||||
{
|
||||
Post(() => callback(state));
|
||||
}
|
||||
|
||||
public void Post(Action action)
|
||||
{
|
||||
_queue.Enqueue(action);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user