Compare commits

..

347 Commits

Author SHA1 Message Date
ALEXTANG
7914660f8c Update SingletonSystem.cs 2024-05-24 14:00:51 +08:00
ALEXTANG
b00679a276 Merge pull request #75 from SunXuebing/main
调整编辑器模式下模块销毁顺序,解决编辑器退出运行后资源管理器销毁了还被调用问题
2024-05-20 14:17:40 +08:00
sxb
cd9a10ccac Update RootModule.cs
修复条件判断
2024-05-20 13:31:57 +08:00
sxb1067
f11098d32e 调整编辑器模式下模块销毁顺序,解决编辑器退出运行后资源管理器销毁了还被调用问题 2024-05-20 11:25:01 +08:00
ALEXTANGXIAO
db6e715fa6 Update ActorEventDispatcher.cs 2024-05-19 22:03:53 +08:00
ALEXTANG
c2edf71ee4 Update AssetItemObject.cs 2024-05-17 17:55:53 +08:00
ALEXTANG
75af7c22c7 Merge pull request #73 from Senfee-Cheng/main
[fix] 移除 `BuildDLLCommand` 构造函数以尝试解决hotfix dll数组被清除的问题
2024-05-17 15:48:27 +08:00
chengshengfei
2f9edf83bf Merge branch 'main' of github.com:Senfee-Cheng/TEngine 2024-05-17 15:45:26 +08:00
chengshengfei
815095efaf [fix] 移除 BuildDLLCommand 构造函数以尝试解决数组被清除的问题 2024-05-17 15:45:06 +08:00
ALEXTANG
3101a64a48 Merge pull request #72 from Severn17/main
yooasset 微信小游戏设置,详情看yooasset微信小游戏支持解决方案文档
2024-05-16 16:05:41 +08:00
yangshiqi
457e0f36a4 yooasset 微信小游戏设置,详情看yooasset微信小游戏支持解决方案文档 2024-05-16 15:19:32 +08:00
ALEXTANG
0bd30def23 移除示例package文件 2024-05-16 13:16:25 +08:00
ALEXTANG
d24db83c8b Update 99-各平台运行RunAble.md 2024-05-16 12:34:55 +08:00
ALEXTANG
18a2840777 Merge pull request #70 from Senfee-Cheng/main
[Platform] Supports console
2024-05-16 10:26:13 +08:00
chengshengfei
1d901514e1 新的平台支持[Sony Console] 2024-05-16 10:18:03 +08:00
chengshengfei
983279c56d 更新文档,添加新增的支持的平台。 2024-05-16 10:14:22 +08:00
ALEXTANG
e9540c620a Merge pull request #69 from Severn17/main
修改编辑器下webgl  平台名字 宏问题
2024-05-14 17:57:38 +08:00
yangshiqi
39be280d88 修改编辑器下webgl 平台名字 宏问题 2024-05-14 17:45:40 +08:00
ALEXTANG
f9f9122027 单例系统完善生命周期、支持Dispose 2024-05-13 14:09:32 +08:00
ALEXTANG
682a0bd786 Update UnityExtension.cs 2024-05-08 17:11:39 +08:00
ALEXTANG
34c514cae8 Update README.md 2024-05-08 10:31:41 +08:00
ALEXTANG
c707cc1a38 GameApp Shutdown 2024-05-08 10:06:33 +08:00
ALEXTANG
f016fdd0a6 Update ReleaseTools.cs 2024-05-07 20:09:15 +08:00
ALEXTANG
4c0f5a77f9 支持编辑器下EnterPlayMode Options 2024-05-07 18:05:41 +08:00
ALEXTANG
ae0d00424f Update ProfilerDefineSymbols.cs 2024-04-30 17:42:36 +08:00
ALEXTANG
c8ecac5815 Update README.md 2024-04-29 12:27:40 +08:00
ALEXTANG
4f8c1cdfdd 修正SpritePostprocessor处理Atlas的override 2024-04-25 15:43:44 +08:00
ALEXTANG
dff043e075 Update SahderVariantCollect
Update SahderVariantCollect
2024-04-24 11:17:38 +08:00
ALEXTANG
e69dc47b8f 修正编辑器调用转表bat 当前路径的问题
修正编辑器调用转表bat 当前路径的问题
2024-04-17 14:27:28 +08:00
ALEXTANG
fc2ef0714c 设置DefaultYooFolderName为package。原本设置默认为yoo。
设置DefaultYooFolderName为package。原本设置默认为yoo。
2024-04-15 19:58:57 +08:00
ALEXTANG
d75c1c8c93 升级YooAsset->2.1.1、UniTask->2.5.4
升级YooAsset->2.1.1、UniTask->2.5.4
2024-04-15 19:37:42 +08:00
ALEXTANG
83bea559e4 Merge pull request #65 from Senfee-Cheng/main 2024-04-12 18:19:10 +08:00
ALEXTANG
26689639ed Merge pull request #64 from ZemelLing/dev-launcher 2024-04-12 18:17:06 +08:00
chengshengfei
bd6ac5f4da 优化代码。 2024-04-12 10:58:06 +08:00
ZemelLing
70dcb03a3f 确保Launcher打开的main场景,而不是其他名称里包含main的场景。 2024-04-11 13:09:16 +08:00
ALEXTANG
59b3649155 优化框架轮询逻辑 ,用脏数据构建Execute数组。
优化框架轮询逻辑 ,用脏数据构建Execute数组。
2024-04-08 15:37:06 +08:00
ALEXTANG
2c025efe3b 修正预加载流程 2024-04-08 14:41:16 +08:00
ALEXTANG
7ae6ef94ba 修正同时对一个图片进行异步SetSprite的处理
修正同时对一个图片进行异步SetSprite的处理
2024-04-07 15:45:32 +08:00
ALEXTANG
d5bb64b314 资源异步加载从缓存中延迟分帧处理。 2024-04-07 15:33:45 +08:00
ALEXTANG
4c34858ce0 Update SettingsUtils.cs 2024-03-29 15:24:02 +08:00
ALEXTANG
5adb2f83e5 Update AssetBundleCollectorSetting.asset 2024-03-29 14:38:44 +08:00
ALEXTANG
f10a89180e 支持边玩边下载,合理化webgl下的流程
支持边玩边下载,合理化webgl下的流程
2024-03-28 15:55:27 +08:00
ALEXTANG
3e3314858e 优化加载游戏物体接口,常用Parent参数前置,编辑器模式下增加超时保护提示
优化加载游戏物体接口,常用Parent参数前置,编辑器模式下增加超时保护提示
2024-03-25 14:27:42 +08:00
ALEXTANGXIAO
da57ed845f 修正同时对一个资源进行异步加载的处理
修正同时对一个资源进行异步加载的处理
2024-03-24 15:58:57 +08:00
ALEXTANGXIAO
df570f453a Create UnityEditor.iOS_I2Loc.Xcode.dll 2024-03-24 15:50:44 +08:00
ALEXTANG
a500a08a30 更新Luban配置表使用文档 2024-03-19 14:25:48 +08:00
ALEXTANG
2daac0e065 默认一键打包使用ClearAndCopyAll 2024-03-19 14:09:27 +08:00
ALEXTANG
514da6e99e Update README.md 2024-03-18 15:44:29 +08:00
ALEXTANG
7f91241df7 Update Version.cs 2024-03-18 15:06:48 +08:00
ALEXTANG
071974ab4f Update GameLogic.asmdef 2024-03-18 15:05:40 +08:00
ALEXTANG
c01e03ff70 Update AssetBundleCollectorSetting.asset 2024-03-18 15:02:23 +08:00
ALEXTANG
6fec792e05 TEngine全面更新,升级YooAsset2.1.1、UniTask、UIWindow、I2Localization
TEngine全面更新,升级YooAsset2.1.1、UniTask、UIWindow、I2Localization
2024-03-18 14:53:26 +08:00
ALEXTANG
04ecf71eab Update ProcedureLoadAssembly.cs 2024-02-27 12:05:26 +08:00
ALEXTANG
693ca5bb3d 编辑器模式重定向所有热更dll,以防编辑器运行AB时出现两份元数据。
编辑器模式重定向所有热更dll,以防编辑器运行AB时出现两份元数据。
2024-01-25 15:10:30 +08:00
ALEXTANG
90f84a2764 更新README
更新README
2023-12-20 12:43:39 +08:00
ALEXTANG
6107b41770 修正动态添加/异步添加ui组件的脏数据问题
修正动态添加/异步添加ui组件的脏数据问题
2023-12-19 18:24:33 +08:00
ALEXTANG
1423a3716a 编辑器模式重定向所有热更dll,以防编辑器运行AB时出现两份元数据。
编辑器模式重定向所有热更dll,以防编辑器运行AB时出现两份元数据。
2023-12-18 19:49:46 +08:00
ALEXTANG
6a87db76ee 优化局部单位事件分发器ActorEventDispatcher,EventRegInfo池化
优化局部单位事件分发器ActorEventDispatcher,EventRegInfo池化
2023-12-15 15:11:12 +08:00
ALEXTANG
3a6170dca6 Update UIWidget.cs 2023-12-15 14:25:41 +08:00
ALEXTANG
9d137d613a 修正Utility.Unity注入非Mono的LateUpdate时序问题
修正Utility.Unity注入非Mono的LateUpdate时序问题
2023-12-15 14:15:08 +08:00
ALEXTANG
ba77ec6b45 Update EventInterfaceGenerate.cs 2023-12-14 15:07:04 +08:00
ALEXTANG
b661da68f2 Update EventInterfaceGenerate.cs 2023-12-14 10:12:56 +08:00
ALEXTANGXIAO
e1040110bb 升级拓展GameEvent,支持基于Interface的方法调用抛出事件,以及自动化根据声明的Interface来生成实现代码。
升级拓展GameEvent,支持基于Interface的方法调用抛出事件,以及自动化根据声明的Interface来生成实现代码。
2023-12-13 23:27:54 +08:00
ALEXTANGXIAO
2d53fa1687 升级HybridCLR 4.0.13=>4.0.14
升级HybridCLR 4.0.13=>4.0.14
2023-12-13 19:27:05 +08:00
ALEXTANG
c4ef07f13e Update UnityExtension.cs 2023-12-12 13:00:53 +08:00
ALEXTANG
1f2d99ddc9 修正UIWindow资源句柄时序导致UI同步显示失效的问题。 2023-12-08 10:38:19 +08:00
ALEXTANG
edf4925a7a UIWidget增加Visible设置
UIWidget增加Visible设置
2023-12-07 16:32:54 +08:00
ALEXTANG
5d67238c8f 统一封装对shader的管理和示例。
统一封装对shader的管理和示例。
2023-12-07 10:55:50 +08:00
ALEXTANG
6cfd352482 关闭ResourceCacheMgr测试日志
关闭ResourceCacheMgr测试日志
2023-12-07 10:30:50 +08:00
ALEXTANG
40373c473d 修改通过Tag加载资源对象集合接口。(Operation需要自行管理生命周期释放)
修改通过Tag加载资源对象集合接口。(Operation需要自行管理生命周期释放)
2023-12-07 10:27:17 +08:00
ALEXTANG
d799f9fdf0 优化资源引用类与资源分组类。 2023-12-06 17:57:54 +08:00
ALEXTANG
15735c3d2d 修正循环列表GetItem,增加普通列表组件。 2023-12-06 14:41:31 +08:00
ALEXTANG
818a74f437 释放资源前判断资源合法性 2023-12-06 11:35:33 +08:00
ALEXTANG
f248757401 消除Editor引用隐患
消除Editor引用隐患
2023-12-01 17:41:43 +08:00
ALEXTANG
6ada0e7de7 移除测试日志 2023-12-01 17:18:13 +08:00
ALEXTANG
7ea472f97e 修正日志重定向下层日志跳转功能
修正日志重定向下层日志跳转功能
2023-12-01 10:45:57 +08:00
ALEXTANG
fb8528ff52 音频代理类增加暂停和取消暂停接口。
音频代理类增加暂停和取消暂停接口。
2023-11-30 16:17:35 +08:00
ALEXTANG
e3ac92ef46 修正音频模块回收池
修正音频模块回收池
2023-11-30 15:30:01 +08:00
ALEXTANG
be6a19c26a 修正Sound轨道不受SoundVolume的影响,调整AudioMixer音频Group命名
修正Sound轨道不受SoundVolume的影响,调整AudioMixer音频Group命名
2023-11-30 13:18:20 +08:00
ALEXTANG
e7f0636f30 拓展细分内存对象生命周期。
拓展细分内存对象生命周期。
2023-11-30 00:13:23 +08:00
ALEXTANG
fb38e96e9e 修正循环列表根据下标获取索引Item
修正循环列表根据下标获取索引Item
2023-11-29 19:48:18 +08:00
ALEXTANG
dd658c7e1d 对象池支持ShutDown
对象池支持ShutDown
2023-11-29 15:39:44 +08:00
ALEXTANG
4d7cb7641d 修正LoadGameObjectAsync接口传参
修正LoadGameObjectAsync接口传参
2023-11-29 15:24:02 +08:00
ALEXTANG
ae075b1fad 修正ProcedureDownloadFile更新时网速计算
修正ProcedureDownloadFile更新时网速计算
2023-11-29 12:55:36 +08:00
ALEXTANG
02827ce3b8 优化/新增超牛逼且很方便使用的对象池。
优化/新增超牛逼且很方便使用的对象池。
2023-11-28 19:36:26 +08:00
ALEXTANG
1a0e3f91e0 优化/新增超牛逼且很方便使用的对象池。
优化/新增超牛逼且很方便使用的对象池。
2023-11-28 15:27:34 +08:00
ALEXTANG
6d376b0e07 增加安全定时器GameTimerTick
增加安全定时器GameTimerTick
2023-11-28 14:25:25 +08:00
ALEXTANGXIAO
cb73c9a9eb 升级HybridCLR 4.0.12=>4.0.13 强烈建议升级,修复了若干bug
升级HybridCLR 4.0.12=>4.0.13 强烈建议升级,修复了若干bug
2023-11-27 22:47:30 +08:00
ALEXTANG
7dda73a7ac 增加泛用加载资源并绑定资源引用到GameObject上。
增加泛用加载资源并绑定资源引用到GameObject上。
2023-11-23 13:34:33 +08:00
ALEXTANG
9bcb636ed7 修正SetSprite接口绑定资源引用关系,避免0引用导致AssetBundle被释放使图片丢失。
修正SetSprite接口绑定资源引用关系,避免0引用导致AssetBundle被释放使图片丢失。
2023-11-23 11:44:43 +08:00
ALEXTANG
bd0cfc5577 增加计时器TimerModule。
增加计时器TimerModule。
2023-11-22 12:20:08 +08:00
ALEXTANG
ff613e4130 更新修复导入图集初始化信息不全的bug
更新修复导入图集初始化信息不全的bug
2023-11-20 17:49:08 +08:00
ALEXTANG
fea1ae2278 Merge pull request #59 from AlanWeekend/main
优化分包资源下载逻辑,统一WebGL平台与其他平台的远程热更资源引用方式
2023-11-20 11:56:04 +08:00
Weekend
866c440479 add:初始化Package流程中增加webgl平台更新update配置 2023-11-19 02:01:15 +08:00
Weekend
48ff839d64 Merge branch 'main' of https://github.com/AlanWeekend/TEngine 2023-11-19 01:43:59 +08:00
Weekend
69be3cfa23 update:统一WebGL平台与其他平台的远程热更资源引用方式 2023-11-19 01:41:47 +08:00
Weekend
5f2c27ecf0 Merge branch 'ALEXTANGXIAO:main' into main 2023-11-18 21:46:00 +08:00
Weekend
ef17cd851b add:优化分包下载 2023-11-18 21:44:24 +08:00
ALEXTANG
f186d6b058 Merge pull request #58 from AlanWeekend/main
增加初始化指定资源包操作,单独下载指定地址的资源文件
2023-11-16 10:52:14 +08:00
Weekend
4385123976 add:设置图片资源支持从指定资源包中加载 2023-11-15 15:39:04 +08:00
Weekend
1334dc30f9 Merge branch 'main' of https://github.com/AlanWeekend/TEngine 2023-11-15 15:15:11 +08:00
Weekend
af822add2c add:下载资源包中指定地址的资源文件 2023-11-15 15:14:47 +08:00
Weekend
ffb1f214ad Merge branch 'ALEXTANGXIAO:main' into main 2023-11-15 14:41:45 +08:00
Weekend
213aaed426 add:初始化指定资源包 2023-11-15 14:40:35 +08:00
ALEXTANG
623d301e41 修正异步创建子Widget时SetParent的问题
修正异步创建子Widget时SetParent的问题
2023-11-15 14:06:49 +08:00
ALEXTANG
2870383afe Resource模块支持操作指定资源包的资源
Resource模块支持操作指定资源包的资源
2023-11-15 10:48:28 +08:00
ALEXTANG
1ad435958a Merge pull request #57 from AlanWeekend/main
add:Resource模块支持操作指定资源包的资源
2023-11-15 10:08:53 +08:00
Weekend
386787c6ec add:Resource模块支持操作指定资源包的资源 2023-11-15 00:14:07 +08:00
ALEXTANG
cd65dde4c3 ReleasePreLoadAssets修正在webgl模式下Shutdown的问题
ReleasePreLoadAssets修正在webgl模式下Shutdown的问题
2023-11-14 16:00:09 +08:00
ALEXTANG
8321e77421 Merge pull request #56 from AlanWeekend/main
fixed:looplistitem重复赋值问题
2023-11-13 13:09:25 +08:00
Weekend
1b6f80952e fixed:looplistitem重复赋值问题
fixed:looplistitem重复赋值问题
2023-11-12 19:49:02 +08:00
ALEXTANG
b52e655c30 更正错误注释
更正错误注释
2023-11-07 11:04:59 +08:00
ALEXTANG
8c0df95626 修正CancellationTokenSource重复Dispose问题
修正CancellationTokenSource重复Dispose问题
2023-11-03 16:58:42 +08:00
ALEXTANG
0d1e308f1c Update ResourceModule.cs 2023-11-03 10:07:25 +08:00
ALEXTANG
f8797538fd Update UIBase.cs 2023-11-03 09:55:36 +08:00
ALEXTANG
fe4e168041 Update ProcedurePreload.cs 2023-11-02 15:35:01 +08:00
ALEXTANG
8e9047d3a3 基于资源框架实现对标签WEBGL_PRELOAD、PRELOAD的预加载。 接口GameModule.Resource.GetPreLoadAsset<T>(location)
基于资源框架实现对标签WEBGL_PRELOAD、PRELOAD的预加载。 接口GameModule.Resource.GetPreLoadAsset<T>(location)
2023-11-02 13:16:05 +08:00
ALEXTANG
04bfaeccc8 示例CLI工作流
示例CLI工作流
2023-11-02 12:55:27 +08:00
ALEXTANG
d66c823c15 更新优化启用UpdateData时UILoadUpdate时序的问题
更新优化启用UpdateData时UILoadUpdate时序的问题
2023-11-02 11:48:47 +08:00
ALEXTANG
0ec1424f0a 升级HybridCLR 4.0.11=>4.0.12
升级HybridCLR 4.0.11=>4.0.12
2023-11-02 11:12:56 +08:00
ALEXTANG
01f8eb9d57 升级HybridCLR 4.0.10=>4.0.11 强烈建议升级,修复了若干bug
升级HybridCLR 4.0.10=>4.0.11 强烈建议升级,修复了若干bug
2023-11-02 10:01:30 +08:00
ALEXTANG
f5021a9688 修正Utility生命周期注入OnDestroy和OnDrawGizmos无效的问题
修正Utility生命周期注入OnDestroy和OnDrawGizmos无效的问题
2023-10-31 12:45:40 +08:00
ALEXTANG
a632f7a5ad Merge pull request #55 from AlanWeekend/main
修复demo流程的下载网速显示错误问题
2023-10-30 23:48:17 +08:00
Weekend
5f968f4154 优化网速计算
优化网速计算
2023-10-30 23:47:07 +08:00
Weekend
c9fe83c2bd Merge branch 'main' of https://github.com/AlanWeekend/TEngine 2023-10-30 23:04:05 +08:00
Weekend
2c00d103cb Update ProcedureDownloadFile.cs
fixed:demo流程的下载网速错误显示问题
2023-10-30 23:04:01 +08:00
ALEXTANG
1d56437d9f Update Utility.Http.cs 2023-10-30 11:15:52 +08:00
ALEXTANG
69db1ff977 修正音频模块音频代理类赋值问题
#54 修正音频模块音频代理类赋值问题
2023-10-30 10:40:22 +08:00
ALEXTANG
48887b1aee 框架支持Shudown不关闭游戏重启
框架支持Shudown不关闭游戏重启
2023-10-27 13:18:12 +08:00
ALEXTANG
381ea8bb8d 增加支持ComponentAutoBindTool自动绑定UI元素组件。
增加支持ComponentAutoBindTool自动绑定UI元素组件。
2023-10-27 10:48:21 +08:00
ALEXTANG
7401edac15 移除UIElement代码绑定工具,为后续AutoBind代码绑定工具做准备
移除UIElement代码绑定工具,为后续AutoBind代码绑定工具做准备
2023-10-27 00:13:04 +08:00
ALEXTANG
b1c7f30be9 ErrorLogger屏幕显示开启与DebugModule关联。
ErrorLogger屏幕显示开启与DebugModule关联。
2023-10-26 23:45:26 +08:00
ALEXTANG
cfaf82a623 释放资源判断资源是否有效
释放资源判断资源是否有效
2023-10-26 14:07:38 +08:00
ALEXTANG
6992d12c6c 修复循环列表主动GetItemByIndex和GetItemList的问题
修复循环列表主动GetItemByIndex和GetItemList的问题
2023-10-26 13:12:35 +08:00
ALEXTANG
119d9683ad Merge pull request #53 from AlanWeekend/main
修复UIListBase和UILoopListWidget赋值问题
2023-10-26 12:49:00 +08:00
ALEXTANG
9478868513 修正HttpDispose
修正HttpDispose
2023-10-26 12:28:06 +08:00
ALEXTANG
6ed32082e1 修正HttpDispose
修正HttpDispose
2023-10-26 11:43:32 +08:00
ALEXTANG
6ee515e8c5 增加局部单位事件分发器的封装。
增加局部单位事件分发器的封装。
2023-10-26 10:28:05 +08:00
ALEXTANG
b839afa76a 释放资源判断资源是否有效、支持YooAssets日志重定向
释放资源判断资源是否有效、支持YooAssets日志重定向
2023-10-26 00:22:02 +08:00
Weekend
d9605b348a 修复UILoopListWidget赋值问题 2023-10-25 22:34:02 +08:00
Weekend
dfef83919c 修复UIListBase和UIUILoopListWidget赋值问题 2023-10-25 22:18:57 +08:00
ALEXTANG
f5f983f220 移除资源模块加载场景,加载场景统一走场景管理模块。增加场景加载进度回调。
移除资源模块加载场景,加载场景统一走场景管理模块。增加场景加载进度回调。
2023-10-23 17:01:06 +08:00
ALEXTANG
d61b1206ee 通过CommandLineReader可以不前台开启Unity实现静默打包,详见CommandLineReader.cs example1
通过CommandLineReader可以不前台开启Unity实现静默打包,详见CommandLineReader.cs example1
2023-10-23 15:22:34 +08:00
ALEXTANG
3650ba1a8b 更新转表bat自动拷贝ConfigSystem
更新转表bat自动拷贝ConfigSystem
2023-10-23 13:00:40 +08:00
ALEXTANG
8f14a4d2cb 日志重定向相关的实用函数。
日志重定向相关的实用函数。
2023-10-23 11:41:44 +08:00
ALEXTANG
dc22e595c9 拓展支持AssetInspector,支持更多文件类型在Inspector显示
拓展支持AssetInspector,支持更多文件类型在Inspector显示
2023-10-23 11:41:33 +08:00
ALEXTANG
0e70f7d446 日志重定向相关的实用函数。
日志重定向相关的实用函数。
2023-10-23 11:27:06 +08:00
ALEXTANG
039569b2d4 提交配置表加载模板
提交配置表加载模板
2023-10-23 10:15:11 +08:00
ALEXTANG
ea38004ba2 luban-next支持懒加载 感谢半仙儿提供支持
luban-next支持懒加载 感谢半仙儿提供支持
2023-10-20 16:24:00 +08:00
ALEXTANG
cc97c0583a 升级luban-next
升级luban-next
2023-10-20 11:53:29 +08:00
ALEXTANG
887094a4b1 升级luban-next
升级luban-next
2023-10-20 11:38:51 +08:00
ALEXTANG
0d09a7e73b 增加场景管理模块。
增加场景管理模块。
2023-10-18 16:42:44 +08:00
ALEXTANG
d8f8514f9d WebGL下不对YooAssets.Destroy();
WebGL下不对YooAssets.Destroy();
2023-10-18 11:23:20 +08:00
ALEXTANG
f2f6b2422f 资源模块优化、UI模块优化,增加接口参数是否使用缓存资源操作句柄。
资源模块优化、UI模块优化,增加接口参数是否使用缓存资源操作句柄、如果需要则不会淘汰缓存队列中的资源清单。
2023-10-18 10:30:12 +08:00
ALEXTANG
3a9cad9397 Update ResourceManager.cs 2023-10-16 16:38:13 +08:00
ALEXTANG
5e70e7972e 更新资源模块接口
更新资源模块接口
2023-10-16 13:03:41 +08:00
ALEXTANG
8d2b4200d6 升级HybridCLR 4.0.8=>4.0.10
升级HybridCLR 4.0.8=>4.0.10
2023-10-13 16:09:34 +08:00
ALEXTANG
b983e85416 资源模块优化-使用资源缓存表以及资源淘汰算法,缓存常用资源,利于获取、淘汰不常用资源。
资源模块优化-使用资源缓存表以及资源淘汰算法,缓存常用资源,利于获取、淘汰不常用资源。
2023-10-13 15:53:16 +08:00
ALEXTANG
99d2afdbd7 事件模块通用命名。
事件模块通用命名。
2023-10-10 21:00:21 +08:00
ALEXTANG
57ce836b3c 升级HybridCLR 4.0.7=>4.0.8
升级HybridCLR 4.0.7=>4.0.8
2023-10-10 20:21:33 +08:00
ALEXTANG
8dce78d6fb 事件模块拓展参数支持。
事件模块拓展参数支持。
2023-10-10 18:13:51 +08:00
ALEXTANG
6d41adffd9 音频模块初始化可自定义音频混响器.
音频模块初始化可自定义音频混响器.
2023-10-10 18:09:35 +08:00
ALEXTANG
cb9129261b 增加通过Tag加载资源对象集合的接口。
增加通过Tag加载资源对象集合的接口。
2023-10-09 19:37:00 +08:00
ALEXTANG
89dd6214d4 修复首次图集导入bug
修复首次图集导入bug
2023-10-09 19:37:00 +08:00
ALEXTANG
1aec76d64c 更新packages
1.升级HybridCLR 4.0.6=>4.0.7
2.使用Unity新版MemoryProfiler
2023-10-09 19:37:00 +08:00
ALEXTANG
859f654f6d 关闭垂直同步,避免设置帧率失效
关闭垂直同步,避免设置帧率失效
2023-10-09 19:37:00 +08:00
ALEXTANG
391d690f9d Merge pull request #49 from ALEXTANGXIAO/TEngine_v4.0.0
TEngine v4.0.0
2023-10-08 16:02:59 +08:00
ALEXTANG
bb0b4104f9 Create about.txt 2023-10-08 15:49:30 +08:00
ALEXTANG
20d0ecd8da Init TEngine4.0.0
Init TEngine4.0.0
2023-10-08 15:47:33 +08:00
ALEXTANG
8c3d6308b9 Init TEngine4.0.0
Init TEngine4.0.0
2023-10-08 15:21:33 +08:00
ALEXTANGXIAO
4c8c37ffd8 异步加载原生文件接口问题修正。
异步加载原生文件接口问题修正。
2023-10-04 18:58:45 +08:00
ALEXTANG
5f694c2bed WebGL毛玻璃效果使用默认
WebGL毛玻璃效果使用默认
2023-09-18 16:41:08 +08:00
ALEXTANG
7ff74bb747 Update GameTime.cs 2023-09-18 16:40:51 +08:00
ALEXTANG
a5de63397a Update 3-4-对象池模块.md 2023-09-18 12:00:36 +08:00
ALEXTANG
13cc62f3f1 增加打印输出协议
增加打印输出协议
2023-09-15 14:07:26 +08:00
ALEXTANGXIAO
95dfac5294 支持普通协议对象数据结构不加入opcode
支持普通协议对象数据结构不加入opcode
2023-09-06 00:13:14 +08:00
ALEXTANGXIAO
14e95107c9 服务器ByteBuf消除警告
服务器ByteBuf消除警告
2023-09-05 23:57:12 +08:00
ALEXTANGXIAO
caf5b2b54e 导出网络协议增加了缓存文件保证一致性
导出网络协议增加了缓存文件保证一致性
2023-09-05 23:56:50 +08:00
ALEXTANG
285483034e Update Exporter.cs 2023-09-05 21:08:54 +08:00
ALEXTANG
1cdd8b63b4 同步服务器导出SceneType
同步服务器导出SceneType
2023-09-05 21:07:33 +08:00
ALEXTANG
4c748df7ac Update ProcedureInitPackage.cs 2023-09-05 20:53:56 +08:00
ALEXTANG
e1229b5a4b 移除无用Extension
移除无用Extension
2023-09-05 20:28:37 +08:00
ALEXTANG
b937fb1a37 [-] 移除Luban无用转表bat
[-] 移除Luban无用转表bat
2023-09-05 19:08:02 +08:00
ALEXTANG
87ab99b363 修复了KCPClientNetwork断开网络连接会发生异常的问题
修复了KCPClientNetwork断开网络连接会发生异常的问题
2023-09-05 14:39:53 +08:00
ALEXTANG
e3a47393f4 [+] 新增游戏物体缓存池ResourcePool
[+] 新增游戏物体缓存池ResourcePool
2023-09-05 14:35:19 +08:00
ALEXTANG
75725314ad FIxed 网络模块对象池复使用问题
FIxed 网络模块对象池复使用问题
2023-09-04 10:06:20 +08:00
ALEXTANG
d3ed2b21b9 Update AudioModule.cs 2023-08-28 20:53:40 +08:00
ALEXTANG
ec34dfbb16 Delete protobuf-net.csproj.meta 2023-08-28 20:41:10 +08:00
ALEXTANG
bd76e3a651 移除示例配置资源.
移除示例配置资源.
2023-08-28 20:35:30 +08:00
ALEXTANG
278c8f23be Update DefaultSettingSerializer.cs 2023-08-28 20:24:31 +08:00
ALEXTANG
42568db2ab Add System.Runtime.CompilerServices.Unsafe.dll
Add System.Runtime.CompilerServices.Unsafe.dll
2023-08-28 20:13:06 +08:00
ALEXTANG
b033c59b00 Aot程序集不查找热更域的Type
Aot程序集不查找热更域的Type
2023-08-28 15:08:18 +08:00
ALEXTANG
04a43a3f11 1.增加重启流程Procedure接口。2.增加进入热更域后的流程Procedure。
1.增加重启流程Procedure接口。2.增加进入热更域后的流程Procedure。
2023-08-26 11:08:46 +08:00
ALEXTANG
54214cdd0b 程序集AssemblyDefine增加对UniTask textmeshpro和dotween的拓展
程序集AssemblyDefine增加对UniTask textmeshpro和dotween的拓展
2023-08-25 14:50:20 +08:00
ALEXTANG
fa870b6228 DotNet支持自定义协议目录
DotNet支持自定义协议目录
2023-08-24 18:38:05 +08:00
ALEXTANG
8a49d3437b Delete proto_csOuterMessage.proto 2023-08-24 17:47:42 +08:00
ALEXTANG
f19b889deb DotNet支持自定义协议目录
DotNet支持自定义协议目录
2023-08-24 17:47:21 +08:00
ALEXTANG
d55f6e29d9 Update RootModule.cs 2023-08-22 11:27:58 +08:00
ALEXTANG
8e4af31f26 修改默认UI资源组的PackRule为PackSeparately
修改默认UI资源组的PackRule为PackSeparately
2023-08-21 20:21:59 +08:00
ALEXTANG
58a4b3e043 YooAsset增加补丁包导入工具和补丁包对比工具
YooAsset增加补丁包导入工具和补丁包对比工具
2023-08-21 20:21:03 +08:00
ALEXTANG
576bf3bb48 增加可选的JsonHelper - NewtonsoftJsonHelper
增加可选的JsonHelper - NewtonsoftJsonHelper
2023-08-21 20:20:28 +08:00
ALEXTANG
d282b81546 增加使用UniTask的常用资源加载接口
增加使用UniTask的常用资源加载接口
2023-08-19 16:23:19 +08:00
ALEXTANG
d6dcd8851c 更新文档
更新文档
2023-08-18 17:49:28 +08:00
ALEXTANG
bbea9c4cee Update UIExtension.cs 2023-08-18 17:10:41 +08:00
ALEXTANG
b1ccb1fd53 Update Utility.Http.cs 2023-08-18 16:54:17 +08:00
ALEXTANG
0f2ad3c71d [+] UI循环列表拓展Grid 用法和List一样
[+] UI循环列表拓展Grid 用法和List一样
2023-08-18 16:32:08 +08:00
ALEXTANG
0e6851e691 Remove unused ogg
Remove unused ogg
2023-08-18 15:24:33 +08:00
ALEXTANG
75b9956261 流程初始音效设置开启 2023-08-18 14:33:49 +08:00
ALEXTANG
401c397fc8 流程初始音效设置开启
流程初始音效设置开启
2023-08-18 14:25:10 +08:00
ALEXTANG
94b314e91f TEngine设置面板增加从Hybrid同步AOT与热更程序集的按钮
TEngine设置面板增加从Hybrid同步AOT与热更程序集的按钮
2023-08-18 13:06:08 +08:00
ALEXTANG
a6573d9336 Update ConfigLoader.cs 2023-08-18 13:05:02 +08:00
ALEXTANG
abf5357f49 给不支持WEBGL的增加宏定义
给不支持WEBGL的增加宏定义
2023-08-18 13:04:53 +08:00
ALEXTANG
aab353cca3 Remove Unused Codes.
Remove Unused Codes.
2023-08-17 23:11:11 +08:00
ALEXTANG
e13071c4db 移除调试luban残留的日志
移除调试luban残留的日志
2023-08-17 23:10:14 +08:00
ALEXTANG
e071c20214 拓展自定义鲁班加载配置,支持懒加载 默认使用懒加载,未使用的配置不会载入内存
拓展自定义鲁班加载配置,支持懒加载 默认使用懒加载,未使用的配置不会载入内存
2023-08-17 23:07:07 +08:00
ALEXTANG
bf73ce333b 拓展自定义鲁班加载配置,支持UniTask异步 默认使用同步加载
拓展自定义鲁班加载配置,支持UniTask异步 默认使用同步加载
2023-08-17 22:00:55 +08:00
ALEXTANG
d7a60002d4 ErrorLog使用异步显示UI
ErrorLog使用异步显示UI
2023-08-17 21:41:30 +08:00
ALEXTANG
61f657322d 增加WebGLUpdateDataUrl
增加WebGLUpdateDataUrl
2023-08-17 21:41:07 +08:00
ALEXTANG
33223dc02e 处理DotNet网络层对WebGL导出的兼容 2023-08-17 21:38:21 +08:00
ALEXTANG
0661c59877 处理DotNet网络层对WebGL导出的兼容
处理DotNet网络层对WebGL导出的兼容
2023-08-17 14:06:09 +08:00
ALEXTANG
7c74e10857 提供单独销毁UIWidget的接口。增加UIWidget异步创建接口。
提供单独销毁UIWidget的接口。增加UIWidget异步创建接口。
2023-08-17 10:59:37 +08:00
ALEXTANG
db935bfb5f DotNet 加入热更域,修正GameProto的依赖
DotNet 加入热更域,修正GameProto的依赖
2023-08-16 15:31:16 +08:00
ALEXTANG
dc6b7bb21e 增加使用UniTask的常用资源加载接口
增加使用UniTask的常用资源加载接口
2023-08-15 17:24:02 +08:00
ALEXTANG
d32f3cb768 增加使用UniTask的常用资源加载接口
增加使用UniTask的常用资源加载接口
2023-08-15 17:22:05 +08:00
ALEXTANG
a32ab30444 修改luban模板配置,支持异步加载配置实例,客户端使用UniTask异步加载配置,避免WebGL不支持原生Task
修改luban模板配置,支持异步加载配置实例,客户端使用UniTask异步加载配置,避免WebGL不支持原生Task
2023-08-15 12:54:15 +08:00
ALEXTANG
aa0d40c758 修改luban模板配置,支持异步加载配置实例
修改luban模板配置,支持异步加载配置实例
2023-08-15 12:07:21 +08:00
ALEXTANGXIAO
5239b89326 DotNet 加入热更域
DotNet 加入热更域
2023-08-12 23:39:21 +08:00
ALEXTANG
53f0ecb6c1 [+] UI循环列表拓展与示例
[+] UI循环列表拓展与示例
2023-08-10 23:25:43 +08:00
ALEXTANG
ea9447d0ea Update ClientGm.cs 2023-08-10 10:10:50 +08:00
ALEXTANG
0c6d59f53e Fixed BehaviourSingleton #45
Fixed BehaviourSingleton #45
2023-08-10 10:09:59 +08:00
ALEXTANG
9986e22d18 [-] Remove Old ProtoGenerate
[-] Remove Old Proto Generate
2023-08-09 14:22:39 +08:00
ALEXTANG
7deb049769 更新Entity接口 泛型获取父级、Define增加unit[]类型
更新Entity接口 泛型获取父级、Define增加unit[]类型
2023-08-09 11:09:38 +08:00
ALEXTANG
fce8bd4d60 Update DebuggerModule.SettingsWindow.cs 2023-08-08 19:54:37 +08:00
ALEXTANG
7ec14c670f Luban配置表拓展分组-分组为c和client的为仅客户端字段s和server为仅服务器字段
Luban配置表拓展分组-分组为c和client的为仅客户端字段s和server为仅服务器字段
2023-08-07 15:14:43 +08:00
ALEXTANGXIAO
efe3d2b25b Update README
Update README
2023-08-06 00:36:29 +08:00
ALEXTANGXIAO
2107282368 Update Readme
Update Readme
2023-08-05 00:54:25 +08:00
ALEXTANG
fb26ea2297 Update AddressableManageComponent.cs 2023-08-04 01:42:26 +08:00
ALEXTANG
9ac150425f Update IntDictionaryConfig.cs 2023-08-04 01:42:00 +08:00
ALEXTANG
36d2c146b0 1、修复了MongoDB在2.18.0以后需要自定义注册ObjectSerializer的问题。 2、Addressable的AddAddressable接口增加isLock参数、用来决定是否需要添加携程锁。 3、修复了APackInfo因为网络多线程的原因导致线程安全的问题。
1、修复了MongoDB在2.18.0以后需要自定义注册ObjectSerializer的问题。
2、Addressable的AddAddressable接口增加isLock参数、用来决定是否需要添加携程锁。
3、修复了APackInfo因为网络多线程的原因导致线程安全的问题。
2023-08-04 01:41:31 +08:00
ALEXTANG
774b73bbbf 注释防裁剪脚本中相机权限的引用
注释防裁剪脚本中相机权限的引用
2023-08-01 16:57:43 +08:00
ALEXTANG
32366eb127 移除防裁剪脚本中相机权限的引用
移除防裁剪脚本中相机权限的引用
2023-08-01 16:54:49 +08:00
ALEXTANG
a843617e5f Update README.md 2023-08-01 10:44:15 +08:00
ALEXTANGXIAO
46b139f7cf 补充IOS运行快照到Books下
补充IOS运行快照到Books下
2023-08-01 00:06:07 +08:00
ALEXTANG
e6ff1dec3f Update BuglyAgent.cs 2023-07-31 20:36:44 +08:00
ALEXTANG
4429732010 Update ConfigLoader.cs 2023-07-31 15:01:11 +08:00
ALEXTANGXIAO
60a5caebae 1、Scene.Create接口增加了一个泛型方法接口。 2、SceneConfig增加了SceneTypeConfig和SceneSubType
1、Scene.Create接口增加了一个泛型方法接口。 2、SceneConfig增加了SceneTypeConfig和SceneSubType
2023-07-29 01:03:35 +08:00
ALEXTANGXIAO
f7c95d8216 服务器启动防呆提示需要转表
服务器启动防呆提示需要转表
2023-07-29 00:12:52 +08:00
ALEXTANGXIAO
98dcb80942 更新编辑器MenuItem导表与导出协议
更新编辑器MenuItem导表与导出协议
2023-07-29 00:03:54 +08:00
ALEXTANG
30192d52cf 调整网络demo场景路径
调整网络demo场景路径
2023-07-27 10:18:02 +08:00
ALEXTANGXIAO
b7b2262d53 合理化服务器命名,使开发者更容易理解。
Scene的routeId更名为locationId
2023-07-27 00:33:39 +08:00
ALEXTANG
d1c93f15d6 Application.OpenURL 调用bat的cmd运行时问题
Application.OpenURL 调用bat的cmd运行时问题
2023-07-26 15:39:20 +08:00
ALEXTANGXIAO
1ac1ff7d56 [+] Update HybridCLR v3.4.0
[+] Update HybridCLR v3.4.0
2023-07-26 00:07:47 +08:00
ALEXTANG
863788f303 Update UIWidget.cs 2023-07-25 23:37:02 +08:00
ALEXTANG
74790c7486 Update UIWindow.cs 2023-07-25 23:34:42 +08:00
ALEXTANG
1c223c8ad0 [+] DOTweenExtension
[+] DOTweenExtension
2023-07-25 17:08:57 +08:00
ALEXTANG
e75b3a4e66 [+] UniTask External YooAsset、Dotween、TextMeshPro 2023-07-25 16:28:09 +08:00
ALEXTANG
91b0995911 [+] UniTask External YooAsset、Dotween、TextMeshPro
[+] UniTask External YooAsset、Dotween、TextMeshPro
2023-07-25 16:22:13 +08:00
ALEXTANG
14c886ea8f [+] UniTask External YooAsset、Dotween、TextMeshPro
[+] UniTask External YooAsset、Dotween、TextMeshPro
2023-07-25 16:20:26 +08:00
ALEXTANG
9babc0ba85 [+] 合理化目录结构 精简非必要插件如确定性物理库以及Recast插件。
[+] 合理化目录结构 精简非必要插件如确定性物理库以及Recast插件。
2023-07-25 14:34:05 +08:00
ALEXTANG
f8056aef32 调整服务器逻辑
1、调整Entity.AddComponent方法添加的组件Id为父组件的Id。
2、增加了ISupportedSingleCollection和ISingleCollectionRoot接口.
3、增加了SingleCollection、用于把子组件保存到单独的数据库表的功能,配合ISupportedSingleCollection和ISingleCollectionRoot。
2023-07-24 16:49:23 +08:00
ALEXTANG
846dc4d4bc Fixed the session dispose
Fixed the session dispose
2023-07-24 13:17:59 +08:00
ALEXTANG
03ab7fb353 Create start_export.bat 2023-07-23 22:18:47 +08:00
ALEXTANG
3c11980e7c Create start_develop.bat 2023-07-23 22:18:45 +08:00
ALEXTANG
c23aa0bd71 Revert "Update Core.csproj"
This reverts commit df76d0b77a.
2023-07-23 21:32:22 +08:00
ALEXTANG
df76d0b77a Update Core.csproj 2023-07-23 21:32:01 +08:00
ALEXTANG
35d2012546 1.替换了KCP为C#版本 2.KCP增加了Memery<T>支持。 3.框架增加了对Memery<T>的支持,服务器网络消息采用Memery<T>,性能得大幅度的提升 4.优化了消息调度执行逻辑
1.替换了KCP为C#版本
2.KCP增加了Memery<T>支持。
3.框架增加了对Memery<T>的支持,服务器网络消息采用Memery<T>,性能得大幅度的提升
4.优化了消息调度执行逻辑
2023-07-23 00:25:47 +08:00
ALEXTANG
c96d20a89a [+] GameFrameworkModuleSystem
[+] GameFrameworkModuleSystem
2023-07-22 17:53:00 +08:00
ALEXTANG
5787d0f9dc [+] GameModuleSystem
[+] GameModuleSystem
2023-07-22 17:51:24 +08:00
ALEXTANG
8b35c8ca07 Update ProjectSettings.asset 2023-07-22 17:50:06 +08:00
ALEXTANG
e5456da482 合理化Address协议逻辑
合理化Address协议逻辑
2023-07-21 17:50:47 +08:00
ALEXTANG
144ba9f222 完善AddressableManageComponent与ClientNetworkComponent
完善AddressableManageComponent与ClientNetworkComponent
2023-07-21 14:32:20 +08:00
ALEXTANG
889fbdc8e1 Update UIGaussianBlurLayer.cs 2023-07-19 17:34:02 +08:00
ALEXTANG
0d177e6868 Update AssetGroup.cs 2023-07-19 17:33:56 +08:00
ALEXTANG
29135228be Update AssetReference.cs 2023-07-19 17:33:52 +08:00
ALEXTANG
c1a1de73cd Update ResourceManager.cs 2023-07-19 17:33:48 +08:00
ALEXTANG
612e9b7eba Update ResourceModule.cs 2023-07-19 17:33:44 +08:00
ALEXTANG
5ed6b8c378 Update UIModule.cs 2023-07-19 17:33:41 +08:00
ALEXTANG
06dad5a68a Update UIWidget.cs 2023-07-19 17:33:28 +08:00
ALEXTANG
9e0462043c Update WindowAttribute.cs 2023-07-19 17:33:25 +08:00
ALEXTANG
c1178e284b Update DUnityUtil.cs 2023-07-19 17:33:21 +08:00
ALEXTANG
8e3dd138a6 Merge pull request #44 from ALEXTANGXIAO/3.0.0-network
TEngine-3.0.0 NetWork And Server
2023-07-19 16:32:03 +08:00
ALEXTANG
405253c507 Update BuildAssetsCommand.cs 2023-07-19 16:03:02 +08:00
ALEXTANG
66ef50a9e0 WebGL适配 2023-07-19 15:51:16 +08:00
ALEXTANG
413f4dcda7 Update GameClient.cs 2023-07-19 15:23:46 +08:00
ALEXTANG
75fdb4d7de Update GameClient.cs 2023-07-19 15:20:05 +08:00
ALEXTANG
1ada1e4e33 Update H_C2G_LoginAddressRequestHandler.cs 2023-07-19 15:20:01 +08:00
ALEXTANG
3848b6aaaa Create AddressableSceneHelper.cs 2023-07-19 15:19:57 +08:00
ALEXTANG
2b33b405c0 Update SceneConfig.cs 2023-07-19 15:19:44 +08:00
ALEXTANG
6766b930d7 更新机器内网配置
更新机器内网配置
2023-07-19 13:08:03 +08:00
ALEXTANG
526baf45fa 完善网络框架,增加服务器断开连接回调 2023-07-18 17:36:48 +08:00
ALEXTANG
a473971cfb Update H_C2G_LoginAddressRequestHandler.cs 2023-07-18 13:06:00 +08:00
ALEXTANG
51effd2c97 Update TCPClientNetwork.cs 2023-07-18 13:05:57 +08:00
ALEXTANG
4205220b64 Network Example2
Network Example2
2023-07-18 13:05:48 +08:00
ALEXTANG
e95c18ca67 Update README.md
Update README.md
2023-07-18 10:08:46 +08:00
ALEXTANG
f5571716a2 Update SkillDisplayData.cs 2023-07-17 20:59:13 +08:00
ALEXTANG
d61a8dfa4b GMPanel
GMPanel
2023-07-17 20:59:04 +08:00
ALEXTANG
068ec709d0 [+] Add GamePlayScene
[+] Add GamePlayScene
2023-07-17 19:00:24 +08:00
ALEXTANG
8b26b790ee GameServerScene
GameServerScene
2023-07-17 18:38:50 +08:00
ALEXTANG
da35b4306b EnumHelper
EnumHelper
2023-07-17 18:29:41 +08:00
ALEXTANG
ee2147e3d9 Update BattleDemo
Update BattleDemo
2023-07-17 18:09:07 +08:00
ALEXTANG
a273e9d5f8 Entitas
Entitas
2023-07-17 15:28:27 +08:00
ALEXTANG
31d4d6c0b8 Update
Update
2023-07-17 01:05:12 +08:00
ALEXTANG
6a6f0591f1 完善Entity状态
完善Entity状态
2023-07-17 01:00:33 +08:00
ALEXTANG
9cd0bac81e 完善登录注册Demo
完善登录注册Demo
2023-07-17 01:00:10 +08:00
ALEXTANG
4abe10eecf IDataBase Last
IDataBase Last
2023-07-16 19:06:45 +08:00
ALEXTANG
bd10297dfa [+] HybridCLR=》v3.3.0
[+] HybridCLR=》v3.3.0
2023-07-16 15:51:44 +08:00
ALEXTANG
7ce72b8aa8 合理化框架
合理化框架
2023-07-16 15:37:38 +08:00
ALEXTANG
c6ecb48944 注册登录Demo
注册登录Demo
2023-07-16 00:57:20 +08:00
ALEXTANG
c178f8bb75 配置目录同步程序集调整
配置目录同步程序集调整
2023-07-15 18:45:38 +08:00
ALEXTANG
d4f160d284 合理化程序集,服务器Logic无需共享的代码存放解决方案目录,无需走Unity目录
合理化程序集,服务器Logic无需共享的代码存放解决方案目录,无需走Unity目录
2023-07-15 18:39:42 +08:00
ALEXTANG
d87653a9fb 调整对于Linux打包的支持
调整对于Linux打包的支持
2023-07-15 00:58:40 +08:00
ALEXTANG
04a5a0e048 Update Demo
Update Demo
2023-07-14 14:23:51 +08:00
ALEXTANG
c825f4d920 Streamline Unity Engineering
Streamline Unity Engineering
2023-07-14 13:38:05 +08:00
ALEXTANG
b3e59b92d6 Update ThirdParty.csproj 2023-07-14 12:47:52 +08:00
ALEXTANG
37af620d71 Update RootNameSpace
Update RootNameSpace
2023-07-14 12:45:06 +08:00
ALEXTANG
493172a925 Update
Update
2023-07-13 23:54:38 +08:00
ALEXTANG
1382db8c61 Update
Update
2023-07-13 21:13:29 +08:00
ALEXTANG
72b7149aa1 Update
Update
2023-07-13 21:02:29 +08:00
ALEXTANG
0c51ae7bdd Update
Update
2023-07-13 19:40:12 +08:00
ALEXTANG
79dc302f14 Update Utility.Http.cs 2023-07-13 19:34:30 +08:00
ALEXTANG
95e4dd93a8 Update
Update
2023-07-13 19:05:40 +08:00
ALEXTANG
2b310c00f2 Update ThirdParty.csproj 2023-07-13 18:22:01 +08:00
ALEXTANG
fbb26ea9ea Update
Update
2023-07-13 18:20:39 +08:00
ALEXTANG
bff8f20af3 Refresh Plugins 2023-07-13 17:41:23 +08:00
ALEXTANG
0c7ce5f28c Refresh Plugins 2023-07-13 17:37:44 +08:00
ALEXTANG
31fc9abdf9 Update OdinModuleConfig.asset 2023-07-13 17:36:37 +08:00
ALEXTANG
a087f40e8a [-] Remove Cysharp.MemoryPack
[-] Remove Cysharp.MemoryPack
2023-07-13 17:31:53 +08:00
ALEXTANG
7b2fc7ce9f Update DotNet sln
Update DotNet sln
2023-07-13 17:27:57 +08:00
ALEXTANG
dc4bb8cc9c Unity低版本语法兼容
Unity低版本语法兼容
2023-07-13 17:24:37 +08:00
ALEXTANG
0c8f3a5f92 [+] TEngineServer
[+] TEngineServer
2023-07-13 17:17:26 +08:00
ALEXTANG
a69f53592e 移除 重构
移除 重构
2023-07-13 12:46:26 +08:00
ALEXTANG
8757e1f550 [+] add et8 csproject
[+] add et8 csproject
2023-07-13 12:26:12 +08:00
ALEXTANG
336d4b2eb9 [+] 接入ET8服务端
[+] 接入ET8服务端
2023-07-13 12:23:48 +08:00
ALEXTANG
e0be062006 Remove old networkmodule 2023-07-12 17:36:29 +08:00
ALEXTANG
5e69129667 Remove old networkmodule
Remove old networkmodule
2023-07-12 17:35:05 +08:00
ALEXTANG
4c39ab79ca [+] Books 2023-07-12 17:28:08 +08:00
ALEXTANG
a710d1cb76 [+] Books 2023-07-10 13:59:56 +08:00
ALEXTANG
8472839394 [+] Books 2023-07-10 13:51:32 +08:00
ALEXTANG
4988c99d31 [+] Books
[+] Books
2023-07-10 12:51:13 +08:00
ALEXTANG
4fa62b2d79 Update README.md 2023-07-10 12:35:48 +08:00
ALEXTANG
f549514d7c Update ResourceManager.cs 2023-07-09 00:07:32 +08:00
ALEXTANG
f588038848 Update UIButtonScale.cs 2023-07-06 19:17:16 +08:00
ALEXTANG
9e0e3ebd50 Fixed the bug of CreateWidgetByPath
Fixed the bug of CreateWidgetByPath
2023-07-06 19:07:45 +08:00
ALEXTANG
b07ef836a9 Update ProcedureLoadAssembly.cs 2023-07-05 15:20:18 +08:00
ALEXTANG
7a1d593195 Update UnityExtension.cs 2023-07-05 15:20:12 +08:00
ALEXTANG
bc113c5c6e [+] Update版本更新时CDN地址也可更新
[+] Update版本更新时CDN地址也可更新
2023-07-04 20:57:26 +08:00
ALEXTANG
753bbdfb82 [+] HybridCLR IOS相机权限问题
大坑 没有任何异常、警告、日志 如果不写这个,就是没有响应
2023-06-29 11:25:33 +08:00
3629 changed files with 94321 additions and 115442 deletions

122
.gitignore vendored
View File

@@ -1,119 +1,15 @@
# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
#
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Mm]emoryCaptures/
/EditorBuild/
# /[Aa]ssets/TResources/DLL/
/[Aa]ssets/StreamingAssets
/BuildBundleInfo/
[Aa]ssets/AATest/
[Aa]ssets/AATest.meta
# Asset meta data should only be ignored when the corresponding asset is also ignored
!/[Aa]ssets/**/*.meta
# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*
# Autogenerated Jetbrains Rider plugin
[Aa]ssets/Plugins/Editor/JetBrains*
# Visual Studio cache directory
.vs/
# Gradle cache directory
.gradle/
# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db
# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
*.mdb.meta
# Unity3D generated file on crash reports
sysinfo.txt
# Builds
*.apk
# Crashlytics generated file
crashlytics-build.properties
# TEnginePersistentDataPath
TEnginePersistentDataPath/
# Hotfix
TEngineHotUpdate/bin
TEngineHotUpdate/obj
#HybirdCLR(HuaTuo)
/HybirdCLRData/
[Hh]ybridCLRData/
#AATemp
[Aa]ssets/AATemp/
[Aa]ssets/AATemp.meta
#Rider
/.idea/
# ABConfig
[Aa]ssets/BuildConfig/
[Aa]ssets/BuildConfig.meta
[Aa]ssets/StreamingAssets/
[Aa]ssets/StreamingAssets.meta
Assets/HybridCLRBuildCache/AssetBundleOutput.meta
Assets/HybridCLRBuildCache/AssetBundleOutput/StandaloneWindows.meta
Assets/HybridCLRBuildCache.meta
Assets/HybridCLRBuildCache/AssetBundleSourceData.meta
Assets/HybridCLRBuildCache/AssetBundleSourceData/StandaloneWindows.meta
#Bundles
Bundles/
#Sandbox
Sandbox/
UnityProject/UserSettings/Layouts/default-2021.dwlt
UnityProject/UserSettings/Search.settings
#Luban
Luban/.cache.meta
Tools/Luban/
Tools/Luban.ClientServer/
Configs/.cache.meta
GenerateDatas/
#HybridCLR
Assets/HybridCLRData.meta
UserSettings/Search.settings
#FileServer
Tools/FileServer/AssetRoot
#Unity UserSettings
UserSettings/Search.index
UserSettings/Layouts/default-2021.dwlt
#UnityOnlineServiceData
Assets/UnityOnlineServiceData.meta
Assets/UnityOnlineServiceData
.DS_Store
UnityProject/ProjectSettings/CommonBurstAotSettings.json
UnityProject/ProjectSettings/BurstAotSettings_StandaloneWindows.json

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: ad23fce0bd282924fa4aedb4da24684f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,69 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!687078895 &4343727234628468602
SpriteAtlas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIRaw_Atlas_Common
serializedVersion: 2
m_EditorData:
serializedVersion: 2
textureSettings:
serializedVersion: 2
anisoLevel: 0
compressionQuality: 0
maxTextureSize: 0
textureCompression: 0
filterMode: 1
generateMipMaps: 0
readable: 0
crunchedCompression: 0
sRGB: 1
platformSettings:
- serializedVersion: 3
m_BuildTarget: iPhone
m_MaxTextureSize: 2048
m_ResizeAlgorithm: 0
m_TextureFormat: 49
m_TextureCompression: 1
m_CompressionQuality: 100
m_CrunchedCompression: 0
m_AllowsAlphaSplitting: 0
m_Overridden: 1
m_AndroidETC2FallbackOverride: 0
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
packingSettings:
serializedVersion: 2
padding: 2
blockOffset: 1
allowAlphaSplitting: 0
enableRotation: 1
enableTightPacking: 0
enableAlphaDilation: 0
secondaryTextureSettings: {}
variantMultiplier: 1
packables:
- {fileID: 21300000, guid: f9a06e163014f4f46b14f4499d3e7240, type: 3}
- {fileID: 21300000, guid: 2761fc23b4aa7e34187ac5ffbc3fad9b, type: 3}
- {fileID: 21300000, guid: d623a2b7e069a4c4592d3da48f476189, type: 3}
- {fileID: 21300000, guid: 57e4117f4cd6ae54284898652e70d553, type: 3}
bindAsDefault: 1
isAtlasV2: 0
cachedData: {fileID: 0}
m_MasterAtlas: {fileID: 0}
m_PackedSprites:
- {fileID: 21300000, guid: 2761fc23b4aa7e34187ac5ffbc3fad9b, type: 3}
- {fileID: 21300000, guid: f9a06e163014f4f46b14f4499d3e7240, type: 3}
- {fileID: 21300000, guid: d623a2b7e069a4c4592d3da48f476189, type: 3}
- {fileID: 21300000, guid: 57e4117f4cd6ae54284898652e70d553, type: 3}
m_PackedSpriteNamesToIndex:
- red_button
- blue_button
- white_background
- white_button
m_RenderDataMap: {}
m_Tag: UIRaw_Atlas_Common
m_IsVariant: 0
m_IsPlaceholder: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f69993ae3e14f924aa33b8747244c587
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 22d1bcdd317c6f64daeb9bf9742495f2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,62 +0,0 @@
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(Network))]
internal sealed class NetworkInspector : GameFrameworkInspector
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!EditorApplication.isPlaying)
{
EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
return;
}
Network t = (Network)target;
if (IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Network Channel Count", t.NetworkChannelCount.ToString());
INetworkChannel[] networkChannels = t.GetAllNetworkChannels();
foreach (INetworkChannel networkChannel in networkChannels)
{
DrawNetworkChannel(networkChannel);
}
}
Repaint();
}
private void DrawNetworkChannel(INetworkChannel networkChannel)
{
EditorGUILayout.BeginVertical("box");
{
EditorGUILayout.LabelField(networkChannel.Name, networkChannel.Connected ? "Connected" : "Disconnected");
EditorGUILayout.LabelField("Service Type", networkChannel.ServiceType.ToString());
EditorGUILayout.LabelField("Address Family", networkChannel.AddressFamily.ToString());
EditorGUILayout.LabelField("Local Address", networkChannel.Connected ? networkChannel.Socket.LocalEndPoint.ToString() : "Unavailable");
EditorGUILayout.LabelField("Remote Address", networkChannel.Connected ? networkChannel.Socket.RemoteEndPoint.ToString() : "Unavailable");
EditorGUILayout.LabelField("Send Packet", Utility.Text.Format("{0} / {1}", networkChannel.SendPacketCount, networkChannel.SentPacketCount));
EditorGUILayout.LabelField("Receive Packet", Utility.Text.Format("{0} / {1}", networkChannel.ReceivePacketCount, networkChannel.ReceivedPacketCount));
EditorGUILayout.LabelField("Miss Heart Beat Count", networkChannel.MissHeartBeatCount.ToString());
EditorGUILayout.LabelField("Heart Beat", Utility.Text.Format("{0:F2} / {1:F2}", networkChannel.HeartBeatElapseSeconds, networkChannel.HeartBeatInterval));
EditorGUI.BeginDisabledGroup(!networkChannel.Connected);
{
if (GUILayout.Button("Disconnect"))
{
networkChannel.Close();
}
}
EditorGUI.EndDisabledGroup();
}
EditorGUILayout.EndVertical();
EditorGUILayout.Separator();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 3301ba180cdc446bbdf823c860ae7a68
timeCreated: 1682045195

View File

@@ -1,489 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
using Object = UnityEngine.Object;
/// <summary>
/// 图集导入管线。
/// </summary>
public class SpritePostprocessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
foreach (var s in importedAssets)
{
EditorSpriteSaveInfo.OnImportSprite(s);
}
foreach (var s in deletedAssets)
{
EditorSpriteSaveInfo.OnDeleteSprite(s);
}
foreach (var s in movedFromAssetPaths)
{
EditorSpriteSaveInfo.OnDeleteSprite(s);
}
foreach (var s in movedAssets)
{
EditorSpriteSaveInfo.OnImportSprite(s);
}
}
}
public static class EditorSpriteSaveInfo
{
private const string NormalAtlasDir = "Assets/Atlas";
private const string UISpritePath = "Assets/AssetRaw/UIRaw";
private const string UIAtlasPath = "Assets/AssetRaw/UIRaw/Atlas";
private const string UIRawPath = "Assets/AssetRaw/UIRaw/UIRaw";
private static List<string> m_dirtyAtlasList = new List<string>();
private static Dictionary<string, List<string>> m_allASprites = new Dictionary<string, List<string>>();
private static Dictionary<string, string> m_uiAtlasMap = new Dictionary<string, string>();
private static bool m_inited = false;
private static bool m_dirty = false;
public static void Init()
{
if (m_inited)
{
return;
}
EditorApplication.update += CheckDirty;
}
public static void CheckDirty()
{
if (m_dirty)
{
m_dirty = false;
AssetDatabase.Refresh();
float lastProgress = -1;
for (int i = 0; i < m_dirtyAtlasList.Count; i++)
{
string atlasName = m_dirtyAtlasList[i];
Debug.Log("更新图集 : " + atlasName);
var curProgress = (float)i / m_dirtyAtlasList.Count;
if (curProgress > lastProgress + 0.01f)
{
lastProgress = curProgress;
var progressText = $"当前进度:{i}/{m_dirtyAtlasList.Count} {atlasName}";
bool cancel = EditorUtility.DisplayCancelableProgressBar("刷新图集" + atlasName, progressText, curProgress);
if (cancel)
{
break;
}
}
bool isUI = atlasName.StartsWith("UIRaw");
SaveAtlas(atlasName, isUI);
}
EditorUtility.ClearProgressBar();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
m_dirtyAtlasList.Clear();
}
}
public static void OnImportSprite(string assetPath)
{
if (!assetPath.StartsWith(UISpritePath))
{
return;
}
TextureImporter ti = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (ti != null)
{
var modify = false;
if (assetPath.StartsWith(UISpritePath))
{
if (ti.textureType != TextureImporterType.Sprite)
{
ti.textureType = TextureImporterType.Sprite;
modify = true;
}
if (!string.IsNullOrEmpty(ti.spritePackingTag))
{
ti.spritePackingTag = string.Empty;
modify = true;
}
var setting = new TextureImporterSettings();
ti.ReadTextureSettings(setting);
if (setting.spriteGenerateFallbackPhysicsShape)
{
setting.spriteGenerateFallbackPhysicsShape = false;
ti.SetTextureSettings(setting);
modify = true;
}
if (IsKeepRawImage(assetPath))
{
//调整android格式
var andPlatformSettings = ti.GetPlatformTextureSettings("Android");
if (!andPlatformSettings.overridden)
{
andPlatformSettings.overridden = true;
modify = true;
}
if (andPlatformSettings.format != TextureImporterFormat.ASTC_6x6)
{
andPlatformSettings.format = TextureImporterFormat.ASTC_6x6;
ti.SetPlatformTextureSettings(andPlatformSettings);
modify = true;
}
//调整ios格式
var iosPlatformSettings = ti.GetPlatformTextureSettings("iPhone");
if (!iosPlatformSettings.overridden)
{
iosPlatformSettings.overridden = true;
modify = true;
}
if (iosPlatformSettings.format != TextureImporterFormat.ASTC_5x5)
{
iosPlatformSettings.format = TextureImporterFormat.ASTC_5x5;
iosPlatformSettings.compressionQuality = 50;
ti.SetPlatformTextureSettings(iosPlatformSettings);
modify = true;
}
}
}
if (modify)
{
ti.SaveAndReimport();
}
if (ti.textureType == TextureImporterType.Sprite)
{
OnProcessSprite(assetPath);
}
}
}
/// <summary>
/// 是否保持散图(不打图集)
/// </summary>
/// <param name="dirPath"></param>
/// <returns></returns>
public static bool IsKeepRawImage(string dirPath)
{
return dirPath.Contains("UIRaw/Raw/") || dirPath.Contains("UIRaw_Raw_");
}
public static string GetSpritePath(string assetPath)
{
string path = assetPath.Substring(0, assetPath.LastIndexOf("."));
path = path.Replace("Assets/AssetRaw/", "");
return path;
}
/// <summary>
/// 根据文件路径,返回图集名称
/// </summary>
/// <param name="fullName"></param>
/// <returns></returns>
public static string GetPackageTag(string fullName)
{
fullName = fullName.Replace("\\", "/");
int idx = fullName.LastIndexOf("UIRaw", StringComparison.Ordinal);
if (idx == -1)
{
return "";
}
if (IsKeepRawImage(fullName))
{
return "";
}
var atlasPath = fullName.Substring(idx);
string str = atlasPath;
str = str.Substring(0, str.LastIndexOf("/", StringComparison.Ordinal)).Replace("/", "_");
return str;
}
public static void OnProcessSprite(string assetPath)
{
if (!assetPath.StartsWith("Assets"))
{
return;
}
if (assetPath.StartsWith("Assets/UIRaw_Delete"))
{
return;
}
Init();
var spriteName = Path.GetFileNameWithoutExtension(assetPath);
var spritePath = GetSpritePath(assetPath);
if (!m_uiAtlasMap.TryGetValue(spriteName, out string oldAssetPath) || spritePath == oldAssetPath)
{
m_uiAtlasMap[spriteName] = spritePath;
m_dirty = true;
}
else
{
Debug.LogError($"有重名的图片:{spriteName}\n旧图集{oldAssetPath}\n新图集{spritePath} ");
m_uiAtlasMap[spriteName] = spritePath;
m_dirty = true;
}
string atlasName = GetPackageTag(assetPath);
if (string.IsNullOrEmpty(atlasName))
{
bool keepRaw = IsKeepRawImage(assetPath);
if (!keepRaw)
{
Debug.LogError($"empty packingTag of asset :{assetPath} !!!");
}
return;
}
else
{
List<string> ret;
if (!m_allASprites.TryGetValue(atlasName, out ret))
{
ret = new List<string>();
m_allASprites.Add(atlasName, ret);
}
if (!ret.Contains(assetPath))
{
ret.Add(assetPath);
m_dirty = true;
if (!m_dirtyAtlasList.Contains(atlasName))
{
m_dirtyAtlasList.Add(atlasName);
}
}
}
}
public static void OnDeleteSprite(string assetPath)
{
if (assetPath.StartsWith("Assets/UIRaw_Delete"))
{
return;
}
if (!assetPath.StartsWith(UISpritePath))
{
return;
}
Init();
string atlasName = GetPackageTag(assetPath);
if (!m_allASprites.TryGetValue(atlasName, out var ret))
{
return;
}
//改成文件名的匹配
if (!ret.Exists(s => Path.GetFileName(s) == Path.GetFileName(assetPath)))
{
return;
}
if (assetPath.StartsWith(UISpritePath))
{
var spriteName = Path.GetFileNameWithoutExtension(assetPath);
if (m_uiAtlasMap.ContainsKey(spriteName))
{
m_uiAtlasMap.Remove(spriteName);
m_dirty = true;
}
}
ret.Remove(assetPath);
m_dirty = true;
if (!m_dirtyAtlasList.Contains(atlasName))
{
m_dirtyAtlasList.Add(atlasName);
}
}
#region
public static void SaveAtlas(string atlasName, bool isUI)
{
List<Object> spriteList = new List<Object>();
if (m_allASprites.ContainsKey(atlasName))
{
var list = m_allASprites[atlasName];
list.Sort(StringComparer.Ordinal);
foreach (var s in list)
{
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(s);
if (sprite != null)
{
spriteList.Add(sprite);
}
}
}
var path = $"{NormalAtlasDir}/{atlasName}.spriteatlas";
if (spriteList.Count == 0)
{
if (File.Exists(path))
{
AssetDatabase.DeleteAsset(path);
}
return;
}
var atlas = new SpriteAtlas();
var setting = new SpriteAtlasPackingSettings
{
blockOffset = 1,
padding = 2,
enableRotation = true
};
bool isOpaque = atlasName.Contains("Opaque");
var textureSetting = new SpriteAtlasTextureSettings
{
generateMipMaps = false,
sRGB = true,
filterMode = FilterMode.Bilinear
};
atlas.SetTextureSettings(textureSetting);
var iphonePlatformSetting = atlas.GetPlatformSettings("iPhone");
if (!iphonePlatformSetting.overridden)
{
iphonePlatformSetting.overridden = true;
iphonePlatformSetting.format = isOpaque ? TextureImporterFormat.ASTC_5x5 : TextureImporterFormat.ASTC_5x5;
iphonePlatformSetting.compressionQuality = 100;
atlas.SetPlatformSettings(iphonePlatformSetting);
}
var androidPlatformSetting = atlas.GetPlatformSettings("Android");
if (isOpaque && !androidPlatformSetting.overridden)
{
androidPlatformSetting.overridden = true;
androidPlatformSetting.format = TextureImporterFormat.ETC_RGB4;
androidPlatformSetting.compressionQuality = 100;
atlas.SetPlatformSettings(androidPlatformSetting);
}
atlas.SetPackingSettings(setting);
atlas.Add(spriteList.ToArray());
AssetDatabase.CreateAsset(atlas, path);
}
#endregion
#region
private static Dictionary<string, List<string>> m_tempAllASprites = new Dictionary<string, List<string>>();
[MenuItem("TEngine/图集/重新生成UI图集")]
static void ForceGenAtlas()
{
Init();
List<string> needSaveAtlas = new List<string>();
m_tempAllASprites.Clear();
var findAssets = AssetDatabase.FindAssets("t:sprite", new[] { UIAtlasPath });
foreach (var findAsset in findAssets)
{
var path = AssetDatabase.GUIDToAssetPath(findAsset);
var atlasName = GetPackageTag(path);
if (!m_tempAllASprites.TryGetValue(atlasName, out var spriteList))
{
spriteList = new List<string>();
m_tempAllASprites[atlasName] = spriteList;
}
if (!spriteList.Contains(path))
{
spriteList.Add(path);
}
}
//有变化的才刷
var iter = m_tempAllASprites.GetEnumerator();
while (iter.MoveNext())
{
bool needSave = false;
var atlasName = iter.Current.Key;
var newSpritesList = iter.Current.Value;
List<string> existSprites;
if (m_allASprites.TryGetValue(atlasName, out existSprites))
{
if (existSprites.Count != newSpritesList.Count)
{
needSave = true;
existSprites.Clear();
existSprites.AddRange(newSpritesList);
}
else
{
for (int i = 0; i < newSpritesList.Count; i++)
{
if (!existSprites.Contains(newSpritesList[i]))
{
needSave = true;
break;
}
}
if (needSave)
{
existSprites.Clear();
existSprites.AddRange(newSpritesList);
}
}
}
else
{
needSave = true;
m_allASprites.Add(atlasName, new List<string>(newSpritesList));
}
if (needSave && !needSaveAtlas.Contains(atlasName))
{
needSaveAtlas.Add(atlasName);
}
}
iter.Dispose();
foreach (var atlas in needSaveAtlas)
{
Debug.LogFormat("Gen atlas:{0}", atlas);
SaveAtlas(atlas, true);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget);
Debug.Log("Gen end");
}
#endregion
}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: b6b7bfca93e005f45999c16054d999e7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,18 +0,0 @@
{
"name": "BattleCore.Runtime",
"rootNamespace": "BattleCore.Runtime",
"references": [
"GUID:aa06d4cc755c979489c256c1bcca1dfb",
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:a90b2d3377c5e4a4db95cc44fb82045e"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 641632c4f8079b94f963b5284d859a12
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 890abd3a957e406ab422fc468ba6c169
timeCreated: 1682353243

View File

@@ -1,6 +0,0 @@
namespace BattleCore.Runtime
{
public static class EntityExtension
{
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b4ef2dfa5ceac99458eb1745131a9c83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,27 +0,0 @@
using UnityEngine;
using Unity.Mathematics;
namespace BattleCore.Runtime
{
public static class MathematicsExt
{
public static int2 ToInt2(this Vector2Int vec) => new int2(vec.x, vec.y);
public static int3 ToInt3(this Vector3Int vec) => new int3(vec.x, vec.y, vec.z);
public static float2 ToFloat2(this Vector2 vec) => new float2(vec.x, vec.y);
public static float3 ToFloat3(this Vector3 vec) => new float3(vec.x, vec.y, vec.z);
public static bool IsEquals(this int2 a, int2 b) => math.all(a == b);
public static bool IsEquals(this int3 a, int3 b) => math.all(a == b);
public static Vector2Int ToVec2(this int2 vec) => new Vector2Int(vec.x, vec.y);
public static Vector3Int ToVec3(this int2 vec) => new Vector3Int(vec.x, vec.y, 0);
public static Vector3Int ToVec3(this int3 vec) => new Vector3Int(vec.x, vec.y, vec.z);
public static Vector2 ToVec2(this float2 vec) => new Vector2(vec.x, vec.y);
public static Vector3 ToVec3(this float3 vec) => new Vector3(vec.x, vec.y, vec.z);
public static int ManhattanDist(this int2 vec) => vec.x + vec.y;
public static int ManhattanDist(this int3 vec) => vec.x + vec.y + vec.z;
public static float ManhattanDist(this float2 vec) => vec.x + vec.y;
public static float ManhattanDist(this float3 vec) => vec.x + vec.y + vec.z;
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 2b0e288b918a41698571ec3d36059851
timeCreated: 1682353251

View File

@@ -1,21 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BattleCore.Runtime
{
public class Empty : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 1fc394f8c6ad5304a82ff84b4263756f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,33 +0,0 @@
using System;
namespace TEngine
{
#region Attribute
[AttributeUsage(AttributeTargets.Class)]
public class UpdateAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class FixedUpdateAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class LateUpdateAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class RoleLoginAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class RoleLogoutAttribute : Attribute
{
}
#endregion
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 80791cccf63d44faa348884ea0c506a2
timeCreated: 1684553027

View File

@@ -1,16 +0,0 @@
namespace GameBase
{
public class BaseClsTemplate<T>
{
protected static T Imp;
/// <summary>
/// Unity工程注册处理函数。
/// </summary>
/// <param name="imp">实现类。</param>
public static void RegisterImp(T imp)
{
Imp = imp;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: bb7ef2f42b33ada47b3543dc7723fcb5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,263 +0,0 @@
using System;
using System.Collections.Generic;
namespace TEngine
{
/// <summary>
/// 通过LogicSys来驱动且具备Unity完整生命周期的单例不继承MonoBehaviour
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class BehaviourSingleton<T> : BaseBehaviourSingleton where T : BaseBehaviourSingleton, new()
{
private static T _instance;
public static T Instance
{
get
{
if (null == _instance)
{
_instance = new T();
Log.Assert(_instance != null);
_instance.Awake();
RegSingleton(_instance);
}
return _instance;
}
}
private static void RegSingleton(BaseBehaviourSingleton inst)
{
BehaviourSingleSystem.Instance.RegSingleton(inst);
}
}
public class BaseBehaviourSingleton
{
public bool IsStart = false;
public virtual void Active()
{
}
public virtual void Awake()
{
}
public virtual bool IsHaveLateUpdate()
{
return false;
}
public virtual void Start()
{
}
/// <summary>
/// 帧更新。
/// <remarks>需要UpdateAttribute。</remarks>
/// </summary>
public virtual void Update()
{
}
/// <summary>
/// 后帧更新。
/// <remarks>需要LateUpdateAttribute。</remarks>
/// </summary>
public virtual void LateUpdate()
{
}
/// <summary>
/// 物理帧更新。
/// <remarks>需要FixedUpdateAttribute。</remarks>
/// </summary>
public virtual void FixedUpdate()
{
}
public virtual void Destroy()
{
}
public virtual void OnPause()
{
}
public virtual void OnResume()
{
}
public virtual void OnDrawGizmos()
{
}
}
public class BehaviourSingleSystem : BaseLogicSys<BehaviourSingleSystem>
{
private readonly List<BaseBehaviourSingleton> _listInst = new List<BaseBehaviourSingleton>();
private readonly List<BaseBehaviourSingleton> _listStart = new List<BaseBehaviourSingleton>();
private readonly List<BaseBehaviourSingleton> _listUpdate = new List<BaseBehaviourSingleton>();
private readonly List<BaseBehaviourSingleton> _listLateUpdate = new List<BaseBehaviourSingleton>();
private readonly List<BaseBehaviourSingleton> _listFixedUpdate = new List<BaseBehaviourSingleton>();
public void RegSingleton(BaseBehaviourSingleton inst)
{
Log.Assert(!_listInst.Contains(inst));
_listInst.Add(inst);
_listStart.Add(inst);
if (HadAttribute<UpdateAttribute>(inst.GetType()))
{
_listUpdate.Add(inst);
}
if (HadAttribute<LateUpdateAttribute>(inst.GetType()))
{
_listLateUpdate.Add(inst);
}
if (HadAttribute<FixedUpdateAttribute>(inst.GetType()))
{
_listFixedUpdate.Add(inst);
}
}
public void UnRegSingleton(BaseBehaviourSingleton inst)
{
if (inst == null)
{
Log.Error($"BaseBehaviourSingleton Is Null");
return;
}
Log.Assert(_listInst.Contains(inst));
if (_listInst.Contains(inst))
{
_listInst.Remove(inst);
}
if (_listStart.Contains(inst))
{
_listStart.Remove(inst);
}
if (_listUpdate.Contains(inst))
{
_listUpdate.Remove(inst);
}
if (_listLateUpdate.Contains(inst))
{
_listLateUpdate.Remove(inst);
}
inst.Destroy();
inst = null;
}
public override void OnUpdate()
{
var listStart = _listStart;
var listToUpdate = _listUpdate;
var listToLateUpdate = _listLateUpdate;
if (listStart.Count > 0)
{
for (int i = 0; i < listStart.Count; i++)
{
var inst = listStart[i];
Log.Assert(!inst.IsStart);
inst.IsStart = true;
inst.Start();
listToUpdate.Add(inst);
if (inst.IsHaveLateUpdate())
{
listToLateUpdate.Add(inst);
}
}
listStart.Clear();
}
var listUpdateCnt = listToUpdate.Count;
for (int i = 0; i < listUpdateCnt; i++)
{
var inst = listToUpdate[i];
TProfiler.BeginFirstSample(inst.GetType().FullName);
inst.Update();
TProfiler.EndFirstSample();
}
}
public override void OnLateUpdate()
{
var listLateUpdate = _listLateUpdate;
var listLateUpdateCnt = listLateUpdate.Count;
for (int i = 0; i < listLateUpdateCnt; i++)
{
var inst = listLateUpdate[i];
TProfiler.BeginFirstSample(inst.GetType().FullName);
inst.LateUpdate();
TProfiler.EndFirstSample();
}
}
public override void OnFixedUpdate()
{
var listFixedUpdate = _listFixedUpdate;
var listFixedUpdateCnt = listFixedUpdate.Count;
for (int i = 0; i < listFixedUpdateCnt; i++)
{
var inst = listFixedUpdate[i];
TProfiler.BeginFirstSample(inst.GetType().FullName);
inst.FixedUpdate();
TProfiler.EndFirstSample();
}
}
public override void OnDestroy()
{
for (int i = 0; i < _listInst.Count; i++)
{
var inst = _listInst[i];
inst.Destroy();
}
}
public override void OnApplicationPause(bool pause)
{
for (int i = 0; i < _listInst.Count; i++)
{
var inst = _listInst[i];
if (pause)
{
inst.OnPause();
}
else
{
inst.OnResume();
}
}
}
public override void OnDrawGizmos()
{
for (int i = 0; i < _listInst.Count; i++)
{
var inst = _listInst[i];
inst.OnDrawGizmos();
}
}
private bool HadAttribute<T>(Type type) where T:Attribute
{
T attribute = Attribute.GetCustomAttribute(type, typeof(T)) as T;
return attribute != null;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: b062b3e32edd4536a4308a3d180842e0
timeCreated: 1681989133

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: dab5f3e08b4367d41b801af29d381ca8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,190 +0,0 @@
using UnityEngine;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Linq;
/*******************************************************************************
//开启一个Loom进程
Loom.RunAsync(() =>
{
aucThread = new Thread(ReceiveMsg);
aucThread.Start();
}
//进程调用主线程方法
MainPack pack = (MainPack)MainPack.Descriptor.Parser.ParseFrom(buffer, 0, len);
Loom.QueueOnMainThread((param) =>
{
UdpHandleResponse(pack);
}, null);
*******************************************************************************/
namespace GameBase
{
/// <summary>
/// Loom多线程通信。
/// <remarks></remarks>
/// </summary>
public class Loom : MonoBehaviour
{
public Dictionary<string, CancellationTokenSource> TokenSourcesDictionary = new Dictionary<string, CancellationTokenSource>();
private static readonly int MaxThreads = 8;
private static int _numThreads;
private static Loom _current;
public static Loom Current
{
get
{
Initialize();
return _current;
}
}
public void Awake()
{
_current = this;
_initialized = true;
}
protected void OnDestroy()
{
}
private static bool _initialized;
private static void Initialize()
{
if (!_initialized)
{
if (!Application.isPlaying)
{
return;
}
_initialized = true;
var obj = new GameObject("[Loom]");
_current = obj.AddComponent<Loom>();
DontDestroyOnLoad(obj);
}
}
public struct NoDelayedQueueItem
{
public Action<object> Action;
public object Param;
}
private readonly List<NoDelayedQueueItem> _actions = new List<NoDelayedQueueItem>();
public struct DelayedQueueItem
{
public float Time;
public Action<object> Action;
public object Param;
}
private readonly List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
private readonly List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
public static void QueueOnMainThread(Action<object> taction, object param, float time = 0f)
{
if (time != 0f)
{
lock (Current._delayed)
{
Current._delayed.Add(new DelayedQueueItem { Time = Time.time + time, Action = taction, Param = param });
}
}
else
{
lock (Current._actions)
{
Current._actions.Add(new NoDelayedQueueItem { Action = taction, Param = param });
}
}
}
public static Thread RunAsync(Action action)
{
Initialize();
while (_numThreads >= MaxThreads)
{
Thread.Sleep(100);
}
Interlocked.Increment(ref _numThreads);
ThreadPool.QueueUserWorkItem(RunAction, action);
return null;
}
private static void RunAction(object action)
{
try
{
((Action)action)();
}
catch
{
// ignored
}
finally
{
Interlocked.Decrement(ref _numThreads);
}
}
void OnDisable()
{
if (_current == this)
{
_current = null;
}
}
private readonly List<NoDelayedQueueItem> _currentActions = new List<NoDelayedQueueItem>();
void Update()
{
if (_actions.Count > 0)
{
lock (_actions)
{
_currentActions.Clear();
_currentActions.AddRange(_actions);
_actions.Clear();
}
for (int i = 0; i < _currentActions.Count; i++)
{
_currentActions[i].Action(_currentActions[i].Param);
}
}
if (_delayed.Count > 0)
{
lock (_delayed)
{
_currentDelayed.Clear();
_currentDelayed.AddRange(_delayed.Where(d => d.Time <= Time.time));
for (int i = 0; i < _currentDelayed.Count; i++)
{
_delayed.Remove(_currentDelayed[i]);
}
}
for (int i = 0; i < _currentDelayed.Count; i++)
{
_currentDelayed[i].Action(_currentDelayed[i].Param);
}
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: eea4adc555e37f842abf5dd24c191d93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 464445719fff48a78021df4a4a6b05a5
timeCreated: 1684552621

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 00565f0d362f4c36836804455e19c3df
timeCreated: 1681990210

View File

@@ -1,27 +0,0 @@
using TEngine;
namespace GameBase
{
/// <summary>
/// 通用单例。
/// </summary>
/// <typeparam name="T">泛型T。</typeparam>
public class Singleton<T> where T : new()
{
private static T _instance;
public static T Instance
{
get
{
if (null == _instance)
{
_instance = new T();
Log.Assert(_instance != null);
}
return _instance;
}
}
}
}

View File

@@ -1,214 +0,0 @@
using System.Collections.Generic;
using TEngine;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace GameBase
{
/// <summary>
/// 单例接口。
/// </summary>
public interface ISingleton
{
void Active();
void Release();
}
/// <summary>
/// 单例管理器(统一化持久和释放)。
/// </summary>
public static class SingletonMgr
{
private static List<ISingleton> _singletonList;
private static Dictionary<string, GameObject> _gameObjects;
private static GameObject _root;
public static GameObject Root
{
get
{
if (_root == null)
{
_root = GameObject.Find("[GameModule]");
if (_root == null)
{
_root = new GameObject("[GameModule]")
{
transform =
{
position = Vector3.zero
}
};
}
Object.DontDestroyOnLoad(_root);
}
return _root;
}
}
public static void Retain(ISingleton go)
{
if (_singletonList == null)
{
_singletonList = new List<ISingleton>();
}
_singletonList.Add(go);
}
public static void Retain(GameObject go)
{
if (_gameObjects == null)
{
_gameObjects = new Dictionary<string, GameObject>();
}
if (!_gameObjects.ContainsKey(go.name))
{
_gameObjects.Add(go.name, go);
if (Application.isPlaying)
{
Object.DontDestroyOnLoad(go);
}
}
}
public static void Release(GameObject go)
{
if (_gameObjects != null && _gameObjects.ContainsKey(go.name))
{
_gameObjects.Remove(go.name);
Object.Destroy(go);
}
}
public static void Release(ISingleton go)
{
if (_singletonList != null && _singletonList.Contains(go))
{
_singletonList.Remove(go);
}
}
public static void Release()
{
if (_gameObjects != null)
{
foreach (var item in _gameObjects)
{
UnityEngine.Object.Destroy(item.Value);
}
_gameObjects.Clear();
}
if (_singletonList != null)
{
for (int i = 0; i < _singletonList.Count; ++i)
{
_singletonList[i].Release();
}
_singletonList.Clear();
}
Resources.UnloadUnusedAssets();
}
public static GameObject GetGameObject(string name)
{
GameObject go = null;
if (_gameObjects != null)
{
_gameObjects.TryGetValue(name, out go);
}
return go;
}
internal static bool ContainsKey(string name)
{
if (_gameObjects != null)
{
return _gameObjects.ContainsKey(name);
}
return false;
}
internal static ISingleton GetSingleton(string name)
{
for (int i = 0; i < _singletonList.Count; ++i)
{
if (_singletonList[i].ToString() == name)
{
return _singletonList[i];
}
}
return null;
}
/// <summary>
/// 释放所有单例。
/// </summary>
public static void ReStart()
{
Release();
SceneManager.LoadScene(0);
}
}
/// <summary>
/// 全局单例对象(非线程安全)。
/// </summary>
/// <typeparam name="T">泛型T。</typeparam>
public abstract class TSingleton<T> : ISingleton where T : TSingleton<T>, new()
{
private static T _instance;
public static T Instance
{
get
{
if (null == _instance)
{
_instance = new T();
_instance.Init();
#if UNITY_EDITOR
Log.Info($"TSingleton Instance:{typeof(T).Name}");
#endif
SingletonMgr.Retain(_instance);
}
return _instance;
}
}
public static bool IsValid => _instance != null;
protected TSingleton()
{
}
protected virtual void Init()
{
}
public virtual void Active()
{
}
public virtual void Release()
{
if (_instance != null)
{
SingletonMgr.Release(_instance);
_instance = null;
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: aa2cb5bb622045d7a6f2a4c4faea3ca6
timeCreated: 1681989590

View File

@@ -1,114 +0,0 @@
using TEngine;
using UnityEngine;
namespace GameBase
{
/// <summary>
/// 具备Unity完整生命周期的单例。
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class UnitySingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
{
var ins = FindObjectOfType<T>();
if (ins != null)
{
var obj = ins.gameObject;
obj.name = typeof(T).Name;
_instance = ins;
SingletonMgr.Retain(obj);
return Instance;
}
System.Type thisType = typeof(T);
string instName = thisType.Name;
GameObject go = SingletonMgr.GetGameObject(instName);
if (go == null)
{
go = GameObject.Find($"[{instName}]");
if (go == null)
{
go = new GameObject($"[{instName}]")
{
transform =
{
position = Vector3.zero
}
};
}
}
_instance = go.GetComponent<T>();
if (_instance == null)
{
_instance = go.AddComponent<T>();
}
if (_instance == null)
{
Log.Error($"Can't create UnitySingleton<{typeof(T)}>");
}
}
return _instance;
}
}
public static T Active()
{
return Instance;
}
public static bool IsValid => _instance != null;
private bool CheckInstance()
{
if (this == Instance)
{
return true;
}
GameObject.Destroy(gameObject);
return false;
}
protected virtual void OnLoad()
{
}
public virtual void Awake()
{
if (CheckInstance())
{
OnLoad();
}
#if UNITY_EDITOR
Log.Debug($"UnitySingleton Instance:{typeof(T).Name}");
#endif
GameObject tEngine = SingletonMgr.Root;
if (tEngine != null)
{
this.gameObject.transform.SetParent(tEngine.transform);
}
}
protected virtual void OnDestroy()
{
Release();
}
public static void Release()
{
if (_instance == null) return;
SingletonMgr.Release(_instance.gameObject);
_instance = null;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 25c99243aa534df5870e36fdf9d36afd
timeCreated: 1681990223

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1d862c80fdc1e684e8ff3b6ae7707b79
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,24 +0,0 @@
using TEngine;
using UnityEngine;
#if ENABLE_URP
using UnityEngine.Rendering.Universal;
#endif
namespace GameLogic
{
public class CameraUtils
{
public static void AddCameraStack(Camera camera,Camera mainCamera)
{
#if ENABLE_URP
if (mainCamera != null)
{
// 通过脚本的方式,只要能找到 camera 不轮是否跨 base 相机的场景,都可以 Add 进 Stack
mainCamera.GetComponent<UniversalAdditionalCameraData>().cameraStack.Add(GameModule.UI.UICamera);
}
#else
Log.Fatal("Could not add camera stack because had no URP-Render-Pip");
#endif
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 6375b5490bbdcc145a24706a6c4e9cb7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4703541a565f5ec4bb35edd81c28958c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,27 +0,0 @@
{
"name": "GameLogic",
"rootNamespace": "GameLogic",
"references": [
"GUID:08c3762f54316454ca6b6fbcb22b40e5",
"GUID:a90b2d3377c5e4a4db95cc44fb82045e",
"GUID:aa06d4cc755c979489c256c1bcca1dfb",
"GUID:641632c4f8079b94f963b5284d859a12",
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:15fc0a57446b3144c949da3e2b9737a9"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.render-pipelines.universal",
"expression": "",
"define": "ENABLE_URP"
}
],
"noEngineReferences": false
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 145b951be40d41dea06e76bd967a5d15
timeCreated: 1682045847

View File

@@ -1,166 +0,0 @@
using TEngine;
namespace GameLogic
{
public enum ClientConnectWatcherStatus
{
StatusInit,
StatusReconnectAuto,
StatusReconnectConfirm,
StatusWaitExit
}
public class ClientConnectWatcher
{
private readonly GameClient _client;
private ClientConnectWatcherStatus _status;
private float _statusTime;
private int _reconnectCnt = 0;
private int _disconnectReason = 0;
private bool _enable = false;
public bool Enable
{
get => _enable;
set
{
if (_enable != value)
{
_enable = value;
if (_enable)
{
OnEnable();
}
else
{
OnDisable();
}
}
}
}
private ClientConnectWatcherStatus Status
{
get => _status;
set
{
if (_status == value) return;
_status = value;
_statusTime = NowTime;
}
}
private float NowTime => GameTime.unscaledTime;
public ClientConnectWatcher(GameClient client)
{
_client = client;
_statusTime = NowTime;
_status = ClientConnectWatcherStatus.StatusInit;
}
public void Update()
{
if (!_enable)
{
return;
}
if (_client.IsEntered)
{
return;
}
switch (_status)
{
case ClientConnectWatcherStatus.StatusInit:
UpdateOnInitStatus();
break;
case ClientConnectWatcherStatus.StatusReconnectAuto:
UpdateOnReconnectAuto();
break;
case ClientConnectWatcherStatus.StatusReconnectConfirm:
UpdateOnReconnectConfirm();
break;
case ClientConnectWatcherStatus.StatusWaitExit:
UpdateOnWaitExit();
break;
}
}
public void OnReConnect()
{
if (_status == ClientConnectWatcherStatus.StatusReconnectConfirm)
{
Status = ClientConnectWatcherStatus.StatusReconnectAuto;
}
}
void UpdateOnInitStatus()
{
int autoReconnectMaxCount = 4;
if (_reconnectCnt <= autoReconnectMaxCount)
{
if (_reconnectCnt == 0)
{
_disconnectReason = _client.LastNetErrCode;
}
Status = ClientConnectWatcherStatus.StatusReconnectAuto;
_reconnectCnt++;
//重连
_client.Reconnect();
}
else
{
Status = ClientConnectWatcherStatus.StatusReconnectConfirm;
_reconnectCnt++;
// UISys.Mgr.ShowUI(GAME_UI_TYPE.Tip_NetDisconn, UISys.Mgr.GetUIWindowParam().SetParam("errCode", m_disconnectReason));
}
}
void UpdateOnReconnectAuto()
{
if (_client.IsEntered)
{
Status = ClientConnectWatcherStatus.StatusInit;
_reconnectCnt = 0;
return;
}
float nowTime = NowTime;
var timeoutTime = 10f;
if (_statusTime + timeoutTime < nowTime)
{
Log.Error("UpdateOnReconnectAuto timeout: {0}", timeoutTime);
//切换到默认的,下一帧继续判断是否需要自动还是手动
Status = ClientConnectWatcherStatus.StatusInit;
}
}
void UpdateOnReconnectConfirm()
{
}
void UpdateOnWaitExit()
{
}
private void OnDisable()
{
Status = ClientConnectWatcherStatus.StatusInit;
_reconnectCnt = 0;
}
private void OnEnable()
{
Status = ClientConnectWatcherStatus.StatusInit;
_reconnectCnt = 0;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 3e4e637f3da340dd9512150c3e2ff087
timeCreated: 1684334948

View File

@@ -1,428 +0,0 @@
using System.Net.Sockets;
using GameBase;
using GameProto;
using TEngine;
using CSPkg = GameProto.CSPkg;
namespace GameLogic
{
public enum GameClientStatus
{
StatusInit, //初始化
StatusReconnect, //重新连接
StatusClose, //断开连接
StatusLogin, //登录中
StatusEnter, //AccountLogin成功进入服务器了
}
public enum CsMsgResult
{
NoError = 0,
NetworkError = 1,
InternalError = 2,
MsgTimeOut = 3,
PingTimeOut = 4,
}
//定义消息回报的回调接口
public delegate void CsMsgDelegate(CsMsgResult result, CSPkg msg);
/// <summary>
/// 统计网络协议的接口
/// </summary>
public delegate void CsMsgStatDelegate(int cmdID, int pkgSize);
public class GameClient : Singleton<GameClient>
{
private readonly INetworkChannel _channel;
private GameClientStatus _status = GameClientStatus.StatusInit;
private readonly MsgDispatcher _dispatcher;
private readonly ClientConnectWatcher _connectWatcher;
private float _lastLogDisconnectErrTime = 0f;
private int _lastNetErrCode = 0;
public int LastNetErrCode => _lastNetErrCode;
public GameClientStatus Status
{
get => _status;
set => _status = value;
}
public bool IsEntered => _status == GameClientStatus.StatusEnter;
/// <summary>
/// 连续心跳超时
/// </summary>
private int _heatBeatTimeoutNum = 0;
private int _ping = -1;
private float NowTime => GameTime.unscaledTime;
private string _lastHost = null;
private int _lastPort = 0;
public GameClient()
{
_connectWatcher = new ClientConnectWatcher(this);
_dispatcher = new MsgDispatcher();
_dispatcher.SetTimeout(5f);
GameEvent.AddEventListener<INetworkChannel,object>(NetworkEvent.NetworkConnectedEvent,OnNetworkConnected);
GameEvent.AddEventListener<INetworkChannel>(NetworkEvent.NetworkClosedEvent,OnNetworkClosed);
GameEvent.AddEventListener<INetworkChannel,NetworkErrorCode,SocketError,string>(NetworkEvent.NetworkErrorEvent,OnNetworkError);
GameEvent.AddEventListener<INetworkChannel,object>(NetworkEvent.NetworkCustomErrorEvent,OnNetworkCustomError);
_channel = Network.Instance.CreateNetworkChannel("GameClient", ServiceType.Tcp, new NetworkChannelHelper());
}
private void OnNetworkConnected(INetworkChannel channel, object userdata)
{
bool isReconnect = (_status == GameClientStatus.StatusReconnect);
//准备登录
Status = GameClientStatus.StatusLogin;
OnServerConnected(isReconnect);
}
private void OnNetworkClosed(INetworkChannel channel)
{
}
private void OnNetworkError(INetworkChannel channel, NetworkErrorCode networkErrorCode, SocketError socketError, string errorMessage)
{
}
private void OnNetworkCustomError(INetworkChannel channel, object userData)
{
}
public void Connect(string host, int port, bool reconnect = false)
{
ResetParam();
if (!reconnect)
{
SetWatchReconnect(false);
}
if (reconnect)
{
// GameEvent.Get<ICommUI>().ShowWaitUITip(WaitUISeq.LOGINWORLD_SEQID, G.R(TextDefine.ID_TIPS_RECONNECTING));
}
else
{
// GameEvent.Get<ICommUI>().ShowWaitUI(WaitUISeq.LOGINWORLD_SEQID);
}
_lastHost = host;
_lastPort = port;
Status = reconnect ? GameClientStatus.StatusReconnect : GameClientStatus.StatusInit;
_channel.Connect(host, port);
}
public void Reconnect()
{
if (string.IsNullOrEmpty(_lastHost) || _lastPort <= 0)
{
// GameModule.UI.ShowTipMsg("Invalid reconnect param");
return;
}
_connectWatcher.OnReConnect();
Connect(_lastHost, _lastPort, true);
}
public void Shutdown()
{
_channel.Close();
_status = GameClientStatus.StatusInit;
}
public void OnServerConnected(bool isReconnect)
{
}
public bool SendCsMsg(CSPkg reqPkg)
{
if (!IsStatusCanSendMsg(reqPkg.Head.MsgId))
{
return false;
}
return DoSendData(reqPkg);
}
public bool IsStatusCanSendMsg(uint msgId)
{
bool canSend = false;
if (_status == GameClientStatus.StatusLogin)
{
canSend = (msgId == (uint)CSMsgID.CsCmdActLoginReq);
}
if (_status == GameClientStatus.StatusEnter)
{
canSend = true;
}
if (!canSend)
{
float nowTime = NowTime;
if (_lastLogDisconnectErrTime + 5 < nowTime)
{
Log.Error("GameClient not connected, send msg failed, msgId[{0}]", msgId);
_lastLogDisconnectErrTime = nowTime;
}
//UISys.Mgr.ShowTipMsg(TextDefine.ID_ERR_NETWORKD_DISCONNECT);
}
return canSend;
}
public bool SendCsMsg(CSPkg reqPkg, uint resCmd, CsMsgDelegate resHandler = null, bool needShowWaitUI = true)
{
if (!IsStatusCanSendMsg(reqPkg.Head.MsgId))
{
return false;
}
var ret = DoSendData(reqPkg);
if (!ret)
{
if (resHandler != null)
{
resHandler(CsMsgResult.InternalError, null);
}
_dispatcher.NotifyCmdError(resCmd, CsMsgResult.InternalError);
}
else
{
//注册消息
if (resHandler != null)
{
_dispatcher.RegSeqHandle(reqPkg.Head.Echo, resCmd, resHandler);
if (reqPkg.Head.Echo > 0 && IsWaitingCmd(resCmd) && needShowWaitUI)
{
// TODO
// GameEvent.Get<ICommUI>().ShowWaitUI(reqPkg.Head.Echo);
}
}
}
return ret;
}
private bool DoSendData(CSPkg reqPkg)
{
if (!IsIgnoreLog(reqPkg.Head.MsgId))
{
Log.Debug("[c-s] CmdId[{0}]\n{1}", reqPkg.Head.MsgId, reqPkg.Body.ToString());
}
var sendRet = _channel.Send(reqPkg);
return sendRet;
}
private bool IsIgnoreLog(uint msgId)
{
bool ignoreLog = false;
switch (msgId)
{
case (uint)CSMsgID.CsCmdHeatbeatReq:
case (uint)CSMsgID.CsCmdHeatbeatRes:
ignoreLog = true;
break;
}
return ignoreLog;
}
public static bool IsWaitingCmd(uint msgId)
{
//心跳包不需要读条等待
if (msgId == (uint)CSMsgID.CsCmdHeatbeatRes)
{
return false;
}
return true;
}
private void ResetParam()
{
_lastLogDisconnectErrTime = 0f;
_heatBeatTimeoutNum = 0;
_lastHbTime = 0f;
_ping = -1;
_lastNetErrCode = 0;
}
public void OnUpdate()
{
_dispatcher.Update();
TickHeartBeat();
CheckHeatBeatTimeout();
_connectWatcher.Update();
}
/// <summary>
/// 注册静态消息
/// </summary>
/// <param name="iCmdID"></param>
/// <param name="msgDelegate"></param>
public void RegCmdHandle(int iCmdID, CsMsgDelegate msgDelegate)
{
_dispatcher.RegCmdHandle((uint)iCmdID, msgDelegate);
}
/// <summary>
/// 移除消息处理函数
/// </summary>
/// <param name="cmdId"></param>
/// <param name="msgDelegate"></param>
public void RmvCmdHandle(int cmdId, CsMsgDelegate msgDelegate)
{
_dispatcher.RmvCmdHandle((uint)cmdId, msgDelegate);
}
/// <summary>
/// 设置加密密钥
/// </summary>
/// <param name="key"></param>
public void SetEncryptKey(string key)
{
}
/// <summary>
/// 设置是否需要监控网络重连。
/// 登录成功后,开启监控,可以自动重连或者提示玩家重连。
/// </summary>
/// <param name="needWatch"></param>
public void SetWatchReconnect(bool needWatch)
{
_connectWatcher.Enable = needWatch;
}
public bool IsNetworkOkAndLogin()
{
return _status == GameClientStatus.StatusEnter;
}
#region
/// <summary>
/// 最近一次心跳的时间
/// </summary>
private float _lastHbTime = 0f;
/// <summary>
/// 心跳间隔
/// </summary>
private readonly float _heartBeatDurTime = 5;
/// <summary>
/// 心跳超时的最大次数
/// </summary>
private const int HeatBeatTimeoutMaxCount = 2;
private bool CheckHeatBeatTimeout()
{
if (_heatBeatTimeoutNum >= HeatBeatTimeoutMaxCount)
{
//断开连接
Shutdown();
//准备重连
_heatBeatTimeoutNum = 0;
Status = GameClientStatus.StatusClose;
Log.Error("heat beat detect timeout");
return false;
}
return true;
}
void TickHeartBeat()
{
if (Status != GameClientStatus.StatusEnter)
{
return;
}
var nowTime = NowTime;
if (_lastHbTime + _heartBeatDurTime < nowTime)
{
_lastHbTime = nowTime;
CSPkg heatPkg = ProtobufUtility.BuildCsMsg((int)CSMsgID.CsCmdHeatbeatReq);
heatPkg.Body.HeatBeatReq = new CSHeatBeatReq { HeatEchoTime = _lastHbTime };
SendCsMsg(heatPkg, (int)CSMsgID.CsCmdHeatbeatRes, HandleHeatBeatRes);
}
}
void HandleHeatBeatRes(CsMsgResult result, CSPkg msg)
{
if (result != CsMsgResult.NoError)
{
//如果是超时了,则标记最近收到包的次数
if (result == CsMsgResult.MsgTimeOut)
{
_heatBeatTimeoutNum++;
Log.Warning("heat beat timeout: {0}", _heatBeatTimeoutNum);
}
}
else
{
var resBody = msg.Body.HeatBeatRes;
float diffTime = NowTime - resBody.HeatEchoTime;
_ping = (int)(diffTime * 1000);
_heatBeatTimeoutNum = 0;
}
}
#endregion
#region Ping值
/// <summary>
/// ping值
/// </summary>
public int Ping
{
get
{
if (IsPingValid())
{
return _ping / 4;
}
else
{
return 0;
}
}
}
public bool IsPingValid()
{
if (IsNetworkOkAndLogin())
{
return _ping >= 0;
}
return false;
}
#endregion
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 8c5441725c9f4d98a7790dc76a6a0c48
timeCreated: 1684331687

View File

@@ -1,265 +0,0 @@
using System;
using System.Collections.Generic;
using GameProto;
using TEngine;
using CSPkg = GameProto.CSPkg;
namespace GameLogic
{
internal class MsgHandleDataToRmv
{
public uint MsgId;
public CsMsgDelegate Handle;
};
class MsgDispatcher
{
const int CheckTimeoutPerframe = 10;
const int MaxMsgHandle = 256;
private readonly CsMsgDelegate[] _aMsgHandles = new CsMsgDelegate[MaxMsgHandle];
private readonly float[] _fMsgRegTime = new float[MaxMsgHandle];
private readonly UInt32[] _adwMsgRegSeq = new UInt32[MaxMsgHandle]; //因为_aiMsgRegResCmdID存储的是hash不能保证一定seqid一样所以这儿存储下用来校验
private readonly uint[] _aiMsgRegResCmdID = new uint[MaxMsgHandle];
UInt32 _dwLastCheckIndex = 0;
private readonly Dictionary<uint, List<CsMsgDelegate>> _mapCmdHandle = new Dictionary<uint, List<CsMsgDelegate>>();
private readonly List<CsMsgStatDelegate> _listStatHandle = new List<CsMsgStatDelegate>();
//防止在处理消息的时候又删除了消息映射,所以这儿加了个队列来做个保护
private readonly List<MsgHandleDataToRmv> _rmvList = new List<MsgHandleDataToRmv>();
private bool _isInHandleLoop = false;
private float _timeout = 5;
// 清理所有的网络消息
public void CleanAllNetMsg()
{
_mapCmdHandle.Clear();
}
public void SetTimeout(float timeout)
{
_timeout = timeout;
}
public void RegSeqHandle(UInt32 dwMsgSeqID, uint iResCmdID, CsMsgDelegate msgDelegate)
{
UInt32 hashIndex = dwMsgSeqID % MaxMsgHandle;
if (_aMsgHandles[hashIndex] != null)
{
OnCallSeqHandle(_adwMsgRegSeq[hashIndex], _aiMsgRegResCmdID[hashIndex]);
NotifyTimeout(_aMsgHandles[hashIndex]);
RmvReg((int)hashIndex);
}
_aMsgHandles[hashIndex] = msgDelegate;
_fMsgRegTime[hashIndex] = NowTime;
_adwMsgRegSeq[hashIndex] = dwMsgSeqID;
_aiMsgRegResCmdID[hashIndex] = iResCmdID;
}
public void RegCmdHandle(uint iCmdID, CsMsgDelegate msgDelegate)
{
if (!_mapCmdHandle.TryGetValue(iCmdID, out var listHandle))
{
listHandle = new List<CsMsgDelegate>();
_mapCmdHandle[iCmdID] = listHandle;
}
if (listHandle != null)
{
if (listHandle.Contains(msgDelegate))
{
Log.Error("-------------repeat RegCmdHandle:{0}-----------", iCmdID);
}
listHandle.Add(msgDelegate);
}
}
/// <summary>
/// 注册统计处理接口
/// </summary>
/// <param name="handler"></param>
public void RegCmdStatHandle(CsMsgStatDelegate handler)
{
_listStatHandle.Add(handler);
}
public void DispatchCmdStat(int cmdID, int pkgSize)
{
foreach (CsMsgStatDelegate handle in _listStatHandle)
{
handle(cmdID, pkgSize);
}
}
public void RmvCmdHandle(uint iCmdID, CsMsgDelegate msgDelegate)
{
if (_isInHandleLoop)
{
MsgHandleDataToRmv toRmvData = new MsgHandleDataToRmv();
toRmvData.MsgId = iCmdID;
toRmvData.Handle = msgDelegate;
_rmvList.Add(toRmvData);
return;
}
if (!_mapCmdHandle.TryGetValue(iCmdID, out var listHandle))
{
return;
}
if (listHandle != null)
{
listHandle.Remove(msgDelegate);
}
}
public void NotifyCmdError(uint iCmdID, CsMsgResult result)
{
NotifyCmdHandle(iCmdID, result, default(CSPkg));
}
protected bool NotifyCmdHandle(uint cmdID, CsMsgResult result, CSPkg pkg)
{
bool ret = false;
if (_mapCmdHandle.TryGetValue(cmdID, out var listHandle))
{
_isInHandleLoop = true;
var rmvList = _rmvList;
rmvList.Clear();
foreach (CsMsgDelegate handle in listHandle)
{
ret = true;
TProfiler.BeginSample("handle");
handle(result, pkg);
TProfiler.EndSample();
}
_isInHandleLoop = false;
//再统一删除掉
int rmvCnt = rmvList.Count;
for (int i = 0; i < rmvCnt; i++)
{
var rmvItem = rmvList[i];
Log.Error("-------------remove cmd handle on loop:{0}-----------", rmvItem.MsgId);
RmvCmdHandle(rmvItem.MsgId, rmvItem.Handle);
}
}
return ret;
}
protected void OnCallSeqHandle(UInt32 echoSeq, uint resCmdID)
{
if (echoSeq > 0)
{
// TODO
// GameEvent.Get<ICommUI>().FinWaitUI(echoSeq);
}
}
protected void NotifyTimeout(CsMsgDelegate msgHandler)
{
msgHandler(CsMsgResult.MsgTimeOut, default(CSPkg));
}
public void NotifySeqError(UInt32 dwSeqID, CsMsgResult result)
{
UInt32 hashIndex = dwSeqID % MaxMsgHandle;
//先判断是否有注册的指定消息
if (_aMsgHandles[hashIndex] != null &&
_adwMsgRegSeq[hashIndex] == dwSeqID)
{
OnCallSeqHandle(dwSeqID, _aiMsgRegResCmdID[hashIndex]);
_aMsgHandles[hashIndex](result, null);
RmvReg((int)hashIndex);
}
}
public bool IsCmdFilterNoLog(int cmdID)
{
switch (cmdID)
{
case (int)CSMsgID.CsCmdHeatbeatRes:
return true;
default:
break;
}
return false;
}
public void NotifyMsg(CSPkg msg)
{
UInt32 dwSeq = msg.Head.Echo;
UInt32 hashIndex = dwSeq % MaxMsgHandle;
//判断是否有固定的消息处理流程
bool bHaveHandle = NotifyCmdHandle(msg.Head.MsgId, CsMsgResult.NoError, msg);
//再判断是否有注册的指定消息
if (_aMsgHandles[hashIndex] != null &&
_adwMsgRegSeq[hashIndex] == dwSeq &&
_aiMsgRegResCmdID[hashIndex] == (int)msg.Head.MsgId)
{
OnCallSeqHandle(_adwMsgRegSeq[hashIndex], _aiMsgRegResCmdID[hashIndex]);
_aMsgHandles[hashIndex](CsMsgResult.NoError, msg);
RmvReg((int)hashIndex);
bHaveHandle = true;
}
if (!bHaveHandle)
{
Log.Debug("there is no handle for Msg[{0}]", msg.Head.MsgId);
}
}
private float NowTime => GameTime.unscaledTime;
public void Update()
{
CheckTimeOut();
}
/// <summary>
/// 定时检查是否请求超时。
/// </summary>
private void CheckTimeOut()
{
float timeout = _timeout;
float nowTime = NowTime;
for (int i = 0; i < CheckTimeoutPerframe; i++)
{
_dwLastCheckIndex = (_dwLastCheckIndex + 1) % MaxMsgHandle;
if (_aMsgHandles[_dwLastCheckIndex] != null)
{
if (_fMsgRegTime[_dwLastCheckIndex] + timeout < nowTime)
{
Log.Error("msg timeout, resCmdID[{0}], reqSeq[{1}]", _aiMsgRegResCmdID[_dwLastCheckIndex],
_adwMsgRegSeq[_dwLastCheckIndex]);
OnCallSeqHandle(_adwMsgRegSeq[_dwLastCheckIndex], _aiMsgRegResCmdID[_dwLastCheckIndex]);
NotifyTimeout(_aMsgHandles[_dwLastCheckIndex]);
RmvReg((int)_dwLastCheckIndex);
}
}
}
}
public void RmvReg(int index)
{
_aMsgHandles[index] = null;
_adwMsgRegSeq[index] = 0;
_aiMsgRegResCmdID[index] = 0;
_fMsgRegTime[index] = 0;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 7d667fb84fed4c5f93a06c464585512f
timeCreated: 1684333223

View File

@@ -1,226 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using GameProto;
using Google.Protobuf;
using TEngine;
namespace GameLogic
{
public class NetworkChannelHelper : INetworkChannelHelper, IMemory
{
private readonly Dictionary<int, Type> _serverToClientPacketTypes = new Dictionary<int, Type>();
private readonly MemoryStream _cachedStream = new MemoryStream(1024 * 8);
private INetworkChannel _networkChannel = null;
/// <summary>
/// 获取消息包头长度。
/// <remarks>4。</remarks>
/// </summary>
public int PacketHeaderLength => sizeof(int);
/// <summary>
/// 初始化网络频道辅助器。
/// </summary>
/// <param name="networkChannel">网络频道。</param>
public void Initialize(INetworkChannel networkChannel)
{
_networkChannel = networkChannel;
GameEvent.AddEventListener<INetworkChannel, object>(NetworkEvent.NetworkConnectedEvent, OnNetworkConnected);
GameEvent.AddEventListener<INetworkChannel>(NetworkEvent.NetworkClosedEvent, OnNetworkClosed);
GameEvent.AddEventListener<INetworkChannel, int>(NetworkEvent.NetworkMissHeartBeatEvent, OnNetworkMissHeartBeat);
GameEvent.AddEventListener<INetworkChannel, NetworkErrorCode, SocketError, string>(NetworkEvent.NetworkErrorEvent, OnNetworkError);
GameEvent.AddEventListener<INetworkChannel, object>(NetworkEvent.NetworkCustomErrorEvent, OnNetworkCustomError);
}
/// <summary>
/// 关闭并清理网络频道辅助器。
/// </summary>
public void Shutdown()
{
GameEvent.RemoveEventListener<INetworkChannel, object>(NetworkEvent.NetworkConnectedEvent, OnNetworkConnected);
GameEvent.RemoveEventListener<INetworkChannel>(NetworkEvent.NetworkClosedEvent, OnNetworkClosed);
GameEvent.RemoveEventListener<INetworkChannel, int>(NetworkEvent.NetworkMissHeartBeatEvent, OnNetworkMissHeartBeat);
GameEvent.RemoveEventListener<INetworkChannel, NetworkErrorCode, SocketError, string>(NetworkEvent.NetworkErrorEvent, OnNetworkError);
GameEvent.RemoveEventListener<INetworkChannel, object>(NetworkEvent.NetworkCustomErrorEvent, OnNetworkCustomError);
_networkChannel = null;
}
/// <summary>
/// 准备进行连接。
/// </summary>
public void PrepareForConnecting()
{
_networkChannel.Socket.ReceiveBufferSize = 1024 * 64;
_networkChannel.Socket.SendBufferSize = 1024 * 64;
}
public CSPkg HeartBeatPack = new CSPkg { Head = new CSPkgHead(), Body = new CSPkgBody() };
/// <summary>
/// 发送心跳消息包。
/// </summary>
/// <returns>是否发送心跳消息包成功。</returns>
public bool SendHeartBeat()
{
HeartBeatPack.Head.MsgId = (uint)CSMsgID.CsCmdHeatbeatReq;
_networkChannel.Send(HeartBeatPack);
return true;
}
/// <summary>
/// 序列化消息包。
/// </summary>
/// <typeparam name="T">消息包类型。</typeparam>
/// <param name="packet">要序列化的消息包。</param>
/// <param name="destination">要序列化的目标流。</param>
/// <returns>是否序列化成功。</returns>
public bool Serialize(CSPkg packet, Stream destination)
{
if (packet == null)
{
Log.Warning("Packet is invalid.");
return false;
}
_cachedStream.SetLength(_cachedStream.Capacity); // 此行防止 Array.Copy 的数据无法写入
_cachedStream.Position = 0L;
global::ProtobufUtility.ToStreamWithHead(packet,_cachedStream);
_cachedStream.WriteTo(destination);
return true;
}
/// <summary>
/// 反序列化消息包头。
/// </summary>
/// <param name="source">要反序列化的来源流。</param>
/// <param name="customErrorData">用户自定义错误数据。</param>
/// <returns>反序列化后的消息包头。</returns>
public IPacketHeader DeserializePacketHeader(Stream source, out object customErrorData)
{
// 注意:此函数并不在主线程调用!
customErrorData = null;
PacketHeader packetHeader = MemoryPool.Acquire<PacketHeader>();
packetHeader.PacketLength = ((MemoryStream)source).GetBuffer()[0];
return packetHeader;
}
/// <summary>
/// 反序列化消息包。
/// </summary>
/// <param name="packetHeader">消息包头。</param>
/// <param name="source">要反序列化的来源流。</param>
/// <param name="customErrorData">用户自定义错误数据。</param>
/// <returns>反序列化后的消息包。</returns>
public CSPkg DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData)
{
// 注意:此函数并不在主线程调用!
customErrorData = null;
PacketHeader scPacketHeader = packetHeader as PacketHeader;
if (scPacketHeader == null)
{
Log.Warning("Packet header is invalid.");
return null;
}
CSPkg csPkg = null;
if (scPacketHeader.IsValid)
{
try
{
csPkg = global::ProtobufUtility.Deserialize(((MemoryStream)source).GetBuffer(),0,scPacketHeader.PacketLength);
Log.Debug("[s-c] CmdId[{0}]\n{1}", csPkg.Head.MsgId, csPkg.ToString());
}
catch (Exception e)
{
Log.Warning(e);
}
}
else
{
Log.Warning("Packet header is invalid.");
}
MemoryPool.Release(scPacketHeader);
return csPkg;
}
private Type GetServerToClientPacketType(int id)
{
if (_serverToClientPacketTypes.TryGetValue(id, out var type))
{
return type;
}
return null;
}
private void OnNetworkConnected(INetworkChannel channel, object userdata)
{
if (channel != _networkChannel)
{
return;
}
Log.Info("Network channel '{0}' connected, local address '{1}', remote address '{2}'.",
channel.Name, channel.Socket.LocalEndPoint.ToString(),
channel.Socket.RemoteEndPoint.ToString());
}
private void OnNetworkClosed(INetworkChannel channel)
{
if (channel != _networkChannel)
{
return;
}
Log.Info("Network channel '{0}' closed.", channel.Name);
}
private void OnNetworkMissHeartBeat(INetworkChannel channel, int missCount)
{
if (channel != _networkChannel)
{
return;
}
Log.Fatal("Network channel '{0}' miss heart beat '{1}' times.", channel.Name, missCount.ToString());
if (missCount < 2)
{
return;
}
channel.Close();
}
private void OnNetworkError(INetworkChannel channel, NetworkErrorCode networkErrorCode, SocketError socketError, string errorMessage)
{
if (channel != _networkChannel)
{
return;
}
Log.Fatal("Network channel '{0}' error, error code is '{1}', error message is '{2}'.", channel.Name, networkErrorCode.ToString(), errorMessage);
channel.Close();
}
private void OnNetworkCustomError(INetworkChannel channel, object userData)
{
if (channel != _networkChannel)
{
return;
}
}
public void Clear()
{
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: bf86ce2ddfb5429abecfb06257c86acd
timeCreated: 1682045961

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: e77590d750cf480baae2468038654bc0
timeCreated: 1681991042

View File

@@ -1,23 +0,0 @@
namespace TEngine
{
/// <summary>
/// 网络地址类型。
/// </summary>
public enum AddressFamily : byte
{
/// <summary>
/// 未知。
/// </summary>
Unknown = 0,
/// <summary>
/// IP 版本 4。
/// </summary>
IPv4,
/// <summary>
/// IP 版本 6。
/// </summary>
IPv6
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: dd8e805430d24bdb8c2679b59ba7c2d6
timeCreated: 1681993653

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 9aefe7f3e0fd485091a20579b29872a7
timeCreated: 1681994393

View File

@@ -1,180 +0,0 @@
using System;
using System.Net;
using System.Net.Sockets;
using GameProto;
using Google.Protobuf;
namespace TEngine
{
/// <summary>
/// 网络频道接口。
/// </summary>
public interface INetworkChannel
{
/// <summary>
/// 获取网络频道名称。
/// </summary>
string Name
{
get;
}
/// <summary>
/// 获取网络频道所使用的 Socket。
/// </summary>
Socket Socket
{
get;
}
/// <summary>
/// 获取是否已连接。
/// </summary>
bool Connected
{
get;
}
/// <summary>
/// 获取网络服务类型。
/// </summary>
ServiceType ServiceType
{
get;
}
/// <summary>
/// 获取网络地址类型。
/// </summary>
AddressFamily AddressFamily
{
get;
}
/// <summary>
/// 获取要发送的消息包数量。
/// </summary>
int SendPacketCount
{
get;
}
/// <summary>
/// 获取累计发送的消息包数量。
/// </summary>
int SentPacketCount
{
get;
}
/// <summary>
/// 获取已接收未处理的消息包数量。
/// </summary>
int ReceivePacketCount
{
get;
}
/// <summary>
/// 获取累计已接收的消息包数量。
/// </summary>
int ReceivedPacketCount
{
get;
}
/// <summary>
/// 获取或设置当收到消息包时是否重置心跳流逝时间。
/// </summary>
bool ResetHeartBeatElapseSecondsWhenReceivePacket
{
get;
set;
}
/// <summary>
/// 获取丢失心跳的次数。
/// </summary>
int MissHeartBeatCount
{
get;
}
/// <summary>
/// 获取或设置心跳间隔时长,以秒为单位。
/// </summary>
float HeartBeatInterval
{
get;
set;
}
/// <summary>
/// 获取心跳等待时长,以秒为单位。
/// </summary>
float HeartBeatElapseSeconds
{
get;
}
/// <summary>
/// 注册网络消息包处理函数。
/// </summary>
/// <param name="msgId">网络消息包id。</param>
/// <param name="msgDelegate">要注册的网络消息包处理函数。</param>
/// <param name="checkRepeat">是否检测重复。</param>
void RegisterMsgHandler(int msgId, CsMsgDelegate msgDelegate, bool checkRepeat = false);
/// <summary>
/// 移除网络消息包处理函数。
/// </summary>
/// <param name="msgId">网络消息包id。</param>
/// <param name="msgDelegate">要注册的网络消息包处理函数。</param>
void RemoveMsgHandler(int msgId, CsMsgDelegate msgDelegate);
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
void Connect(string ipAddress, int port);
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
void Connect(IPAddress ipAddress, int port);
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
/// <param name="userData">用户自定义数据。</param>
void Connect(IPAddress ipAddress, int port, object userData);
/// <summary>
/// 关闭网络频道。
/// </summary>
void Close();
/// <summary>
/// 向远程主机发送消息包。
/// </summary>
/// <typeparam name="T">消息包类型。</typeparam>
/// <param name="packet">要发送的消息包。</param>
/// <returns>消息包是否发送成功。</returns>
bool Send(CSPkg packet);
/// <summary>
/// 向远程主机发送消息包并注册消息回调。
/// </summary>
/// <typeparam name="T">消息包类型。</typeparam>
/// <param name="packet">要发送的消息包。</param>
/// <param name="resHandler">要注册的回调。</param>
/// <param name="needShowWaitUI">是否需要等待UI。</param>
/// <returns>消息包是否发送成功。</returns>
bool Send(CSPkg packet, CsMsgDelegate resHandler, bool needShowWaitUI = false);
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 09b554ed41c546a1bc40e5be392f836a
timeCreated: 1681993830

View File

@@ -1,67 +0,0 @@
using System.IO;
using GameProto;
namespace TEngine
{
/// <summary>
/// 网络频道辅助器接口。
/// </summary>
public interface INetworkChannelHelper
{
/// <summary>
/// 获取消息包头长度。
/// </summary>
int PacketHeaderLength
{
get;
}
/// <summary>
/// 初始化网络频道辅助器。
/// </summary>
/// <param name="networkChannel">网络频道。</param>
void Initialize(INetworkChannel networkChannel);
/// <summary>
/// 关闭并清理网络频道辅助器。
/// </summary>
void Shutdown();
/// <summary>
/// 准备进行连接。
/// </summary>
void PrepareForConnecting();
/// <summary>
/// 发送心跳消息包。
/// </summary>
/// <returns>是否发送心跳消息包成功。</returns>
bool SendHeartBeat();
/// <summary>
/// 序列化消息包。
/// </summary>
/// <typeparam name="T">消息包类型。</typeparam>
/// <param name="packet">要序列化的消息包。</param>
/// <param name="destination">要序列化的目标流。</param>
/// <returns>是否序列化成功。</returns>
bool Serialize(CSPkg packet, Stream destination);
/// <summary>
/// 反序列化消息包头。
/// </summary>
/// <param name="source">要反序列化的来源流。</param>
/// <param name="customErrorData">用户自定义错误数据。</param>
/// <returns>反序列化后的消息包头。</returns>
IPacketHeader DeserializePacketHeader(Stream source, out object customErrorData);
/// <summary>
/// 反序列化消息包。
/// </summary>
/// <param name="packetHeader">消息包头。</param>
/// <param name="source">要反序列化的来源流。</param>
/// <param name="customErrorData">用户自定义错误数据。</param>
/// <returns>反序列化后的消息包。</returns>
CSPkg DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData);
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 1f847791db5a4e6cbbc39dd56a6888d9
timeCreated: 1681993713

View File

@@ -1,84 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
namespace TEngine
{
/// <summary>
/// 网络管理器接口。
/// </summary>
public interface INetworkManager
{
/// <summary>
/// 获取网络频道数量。
/// </summary>
int NetworkChannelCount { get; }
/// <summary>
/// 网络连接成功事件。
/// </summary>
event Action<INetworkChannel, object> NetworkConnected;
/// <summary>
/// 网络连接关闭事件。
/// </summary>
event Action<INetworkChannel> NetworkClosed;
/// <summary>
/// 网络心跳包丢失事件。
/// </summary>
event Action<INetworkChannel, int> NetworkMissHeartBeat;
/// <summary>
/// 网络错误事件。
/// </summary>
event Action<INetworkChannel, NetworkErrorCode, SocketError, string> NetworkError;
/// <summary>
/// 用户自定义网络错误事件。
/// </summary>
event Action<INetworkChannel, object> NetworkCustomError;
/// <summary>
/// 检查是否存在网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否存在网络频道。</returns>
bool HasNetworkChannel(string name);
/// <summary>
/// 获取网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>要获取的网络频道。</returns>
INetworkChannel GetNetworkChannel(string name);
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <returns>所有网络频道。</returns>
INetworkChannel[] GetAllNetworkChannels();
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <param name="results">所有网络频道。</param>
void GetAllNetworkChannels(List<INetworkChannel> results);
/// <summary>
/// 创建网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="serviceType">网络服务类型。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
/// <returns>要创建的网络频道。</returns>
INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper);
/// <summary>
/// 销毁网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否销毁网络频道成功。</returns>
bool DestroyNetworkChannel(string name);
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 7de8458fc50e4cd3b49ef73d35ad9763
timeCreated: 1681993806

View File

@@ -1,16 +0,0 @@
namespace TEngine
{
/// <summary>
/// 网络消息包头接口。
/// </summary>
public interface IPacketHeader
{
/// <summary>
/// 获取网络消息包长度。
/// </summary>
int PacketLength
{
get;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 7659e4a617d84126b0a548077fb4fdcc
timeCreated: 1681994226

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 6d988d26345f402f9177488d8921184f
timeCreated: 1682092063

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 6dff8f4f5dd94df49bf6d616fb11cc9c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,71 +0,0 @@
using System.Buffers;
using Cysharp.Threading.Tasks;
namespace System.Net.Sockets.Kcp
{
/// <summary>
/// 用于调试的KCP IO 类没有Kcp功能
/// </summary>
public class FakeKcpIO : IKcpIO
{
QueuePipe<byte[]> recv = new QueuePipe<byte[]>();
public int Input(ReadOnlySpan<byte> span)
{
byte[] buffer = new byte[span.Length];
span.CopyTo(buffer);
recv.Write(buffer);
return 0;
}
public int Input(ReadOnlySequence<byte> span)
{
byte[] buffer = new byte[span.Length];
span.CopyTo(buffer);
return Input(buffer);
}
public async UniTask RecvAsync(IBufferWriter<byte> writer, object options = null)
{
var buffer = await recv.ReadAsync().ConfigureAwait(false);
var target = writer.GetMemory(buffer.Length);
buffer.AsSpan().CopyTo(target.Span);
writer.Advance(buffer.Length);
}
public async UniTask<int> RecvAsync(ArraySegment<byte> buffer, object options = null)
{
var temp = await recv.ReadAsync().ConfigureAwait(false);
temp.AsSpan().CopyTo(buffer);
return temp.Length;
}
QueuePipe<byte[]> send = new QueuePipe<byte[]>();
public int Send(ReadOnlySpan<byte> span, object options = null)
{
byte[] buffer = new byte[span.Length];
span.CopyTo(buffer);
send.Write(buffer);
return 0;
}
public int Send(ReadOnlySequence<byte> span, object options = null)
{
byte[] buffer = new byte[span.Length];
span.CopyTo(buffer);
return Send(buffer);
}
public async UniTask OutputAsync(IBufferWriter<byte> writer, object options = null)
{
var buffer = await send.ReadAsync().ConfigureAwait(false);
Write(writer, buffer);
}
private static void Write(IBufferWriter<byte> writer, byte[] buffer)
{
var span = writer.GetSpan(buffer.Length);
buffer.AsSpan().CopyTo(span);
writer.Advance(buffer.Length);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e3c2f9de3c34ffc409549b86ac3fc530
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,147 +0,0 @@
using BufferOwner = System.Buffers.IMemoryOwner<byte>;
using System.Buffers;
using Cysharp.Threading.Tasks;
namespace System.Net.Sockets.Kcp
{
/// <summary>
/// Kcp回调
/// </summary>
public interface IKcpCallback
{
/// <summary>
/// kcp 发送方向输出
/// </summary>
/// <param name="buffer">kcp 交出发送缓冲区控制权,缓冲区来自<see cref="RentBuffer(int)"/></param>
/// <param name="avalidLength">数据的有效长度</param>
/// <returns>不需要返回值</returns>
/// <remarks>通过增加 avalidLength 能够在协议栈中有效的减少数据拷贝</remarks>
void Output(BufferOwner buffer, int avalidLength);
}
/// <summary>
/// Kcp回调
/// </summary>
/// <remarks>
/// 失败设计,<see cref="KcpOutputWriter.Output(BufferOwner, int)"/>。IMemoryOwner是没有办法代替的。
/// 这里只相当于把 IKcpCallback 和 IRentable 和并。
/// </remarks>
public interface IKcpOutputWriter : IBufferWriter<byte>
{
int UnflushedBytes { get; }
void Flush();
}
/// <summary>
/// 外部提供缓冲区,可以在外部链接一个内存池
/// </summary>
public interface IRentable
{
/// <summary>
/// 外部提供缓冲区,可以在外部链接一个内存池
/// </summary>
BufferOwner RentBuffer(int length);
}
public interface IKcpSetting
{
int Interval(int interval);
/// <summary>
/// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
/// </summary>
/// <param name="nodelay">0:disable(default), 1:enable</param>
/// <param name="interval">internal update timer interval in millisec, default is 100ms</param>
/// <param name="resend">0:disable fast resend(default), 1:enable fast resend</param>
/// <param name="nc">0:normal congestion control(default), 1:disable congestion control</param>
/// <returns></returns>
int NoDelay(int nodelay, int interval, int resend, int nc);
/// <summary>
/// change MTU size, default is 1400
/// <para>** 这个方法不是线程安全的。请在没有发送和接收时调用 。</para>
/// </summary>
/// <param name="mtu"></param>
/// <returns></returns>
/// <remarks>
/// 如果没有必要不要修改Mtu。过小的Mtu会导致分片数大于接收窗口造成kcp阻塞冻结。
/// </remarks>
int SetMtu(int mtu = 1400);
/// <summary>
/// set maximum window size: sndwnd=32, rcvwnd=128 by default
/// </summary>
/// <param name="sndwnd"></param>
/// <param name="rcvwnd"></param>
/// <returns></returns>
/// <remarks>
/// 如果没有必要请不要修改。注意确保接收窗口必须大于最大分片数。
/// </remarks>
int WndSize(int sndwnd = 32, int rcvwnd = 128);
}
public interface IKcpUpdate
{
void Update(in DateTimeOffset time);
}
public interface IKcpSendable
{
/// <summary>
/// 将要发送到网络的数据Send到kcp协议中
/// </summary>
/// <param name="span"></param>
/// <param name="options"></param>
int Send(ReadOnlySpan<byte> span, object options = null);
/// <summary>
/// 将要发送到网络的数据Send到kcp协议中
/// </summary>
/// <param name="span"></param>
/// <param name="options"></param>
int Send(ReadOnlySequence<byte> span, object options = null);
}
public interface IKcpInputable
{
/// <summary>
/// 下层收到数据后添加到kcp协议中
/// </summary>
/// <param name="span"></param>
int Input(ReadOnlySpan<byte> span);
/// <summary>
/// 下层收到数据后添加到kcp协议中
/// </summary>
/// <param name="span"></param>
int Input(ReadOnlySequence<byte> span);
}
/// <summary>
/// kcp协议输入输出标准接口
/// </summary>
public interface IKcpIO : IKcpSendable, IKcpInputable
{
/// <summary>
/// 从kcp中取出一个整合完毕的数据包
/// </summary>
/// <returns></returns>
UniTask RecvAsync(IBufferWriter<byte> writer, object options = null);
/// <summary>
/// 从kcp中取出一个整合完毕的数据包
/// </summary>
/// <param name="buffer"></param>
/// <param name="options"></param>
/// <returns>接收数据长度</returns>
UniTask<int> RecvAsync(ArraySegment<byte> buffer, object options = null);
/// <summary>
/// 从kcp协议中取出需要发送到网络的数据。
/// </summary>
/// <param name="writer"></param>
/// <param name="options"></param>
/// <returns></returns>
UniTask OutputAsync(IBufferWriter<byte> writer, object options = null);
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b0ca98e42147b3948bc8d30f24e9c366
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,88 +0,0 @@
namespace System.Net.Sockets.Kcp
{
/// <summary>
/// Kcp报头
/// https://zhuanlan.zhihu.com/p/559191428
/// </summary>
public interface IKcpHeader
{
/// <summary>
/// 会话编号,两方一致才会通信
/// </summary>
uint conv { get; set; }
/// <summary>
/// 指令类型
/// </summary>
/// <remarks>
/// <para/> IKCP_CMD_PUSH = 81 // cmd: push data 数据报文
/// <para/> IKCP_CMD_ACK = 82 // cmd: ack 确认报文
/// <para/> IKCP_CMD_WASK = 83 // cmd: window probe (ask) 窗口探测报文,询问对端剩余接收窗口的大小.
/// <para/> IKCP_CMD_WINS = 84 // cmd: window size (tell) 窗口通知报文,通知对端剩余接收窗口的大小.
/// </remarks>
byte cmd { get; set; }
/// <summary>
/// 剩余分片数量,表示随后还有多少个报文属于同一个包。
/// </summary>
byte frg { get; set; }
/// <summary>
/// 自己可用窗口大小
/// </summary>
ushort wnd { get; set; }
/// <summary>
/// 发送时的时间戳 <seealso cref="DateTimeOffset.ToUnixTimeMilliseconds"/>
/// </summary>
uint ts { get; set; }
/// <summary>
/// 编号 确认编号或者报文编号
/// </summary>
uint sn { get; set; }
/// <summary>
/// 代表编号前面的所有报都收到了的标志
/// </summary>
uint una { get; set; }
/// <summary>
/// 数据内容长度
/// </summary>
uint len { get; }
}
public interface IKcpSegment : IKcpHeader
{
/// <summary>
/// 重传的时间戳。超过当前时间重发这个包
/// </summary>
uint resendts { get; set; }
/// <summary>
/// 超时重传时间,根据网络去定
/// </summary>
uint rto { get; set; }
/// <summary>
/// 快速重传机制,记录被跳过的次数,超过次数进行快速重传
/// </summary>
uint fastack { get; set; }
/// <summary>
/// 重传次数
/// </summary>
uint xmit { get; set; }
/// <summary>
/// 数据内容
/// </summary>
Span<byte> data { get; }
/// <summary>
/// 将IKcpSegment编码成字节数组并返回总长度包括Kcp报头
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
int Encode(Span<byte> buffer);
}
public interface ISegmentManager<Segment> where Segment : IKcpSegment
{
Segment Alloc(int appendDateSize);
void Free(Segment seg);
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a9259bb6b548e46459cc766d8fe2faeb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,387 +0,0 @@
using System.Buffers;
using BufferOwner = System.Buffers.IMemoryOwner<byte>;
namespace System.Net.Sockets.Kcp
{
public class Kcp<Segment> : KcpCore<Segment>
where Segment : IKcpSegment
{
/// <summary>
/// create a new kcp control object, 'conv' must equal in two endpoint
/// from the same connection.
/// </summary>
/// <param name="conv_"></param>
/// <param name="callback"></param>
/// <param name="rentable">可租用内存的回调</param>
public Kcp(uint conv_, IKcpCallback callback, IRentable rentable = null)
: base(conv_)
{
callbackHandle = callback;
this.rentable = rentable;
}
//extension 重构和新增加的部分============================================
IRentable rentable;
/// <summary>
/// 如果外部能够提供缓冲区则使用外部缓冲区否则new byte[]
/// </summary>
/// <param name="needSize"></param>
/// <returns></returns>
internal protected override BufferOwner CreateBuffer(int needSize)
{
var res = rentable?.RentBuffer(needSize);
if (res == null)
{
return base.CreateBuffer(needSize);
}
else
{
if (res.Memory.Length < needSize)
{
throw new ArgumentException($"{nameof(rentable.RentBuffer)} 指定的委托不符合标准,返回的" +
$"BufferOwner.Memory.Length 小于 {nameof(needSize)}");
}
}
return res;
}
/// <summary>
/// TryRecv Recv设计上同一时刻只允许一个线程调用。
/// <para/>因为要保证数据顺序多个线程同时调用Recv也没有意义。
/// <para/>所以只需要部分加锁即可。
/// </summary>
/// <returns></returns>
public (BufferOwner buffer, int avalidLength) TryRecv()
{
var peekSize = -1;
lock (rcv_queueLock)
{
if (rcv_queue.Count == 0)
{
///没有可用包
return (null, -1);
}
var seq = rcv_queue[0];
if (seq.frg == 0)
{
peekSize = (int)seq.len;
}
if (rcv_queue.Count < seq.frg + 1)
{
///没有足够的包
return (null, -1);
}
uint length = 0;
foreach (var item in rcv_queue)
{
length += item.len;
if (item.frg == 0)
{
break;
}
}
peekSize = (int)length;
if (peekSize <= 0)
{
return (null, -2);
}
}
var buffer = CreateBuffer(peekSize);
var recvlength = UncheckRecv(buffer.Memory.Span);
return (buffer, recvlength);
}
/// <summary>
/// TryRecv Recv设计上同一时刻只允许一个线程调用。
/// <para/>因为要保证数据顺序多个线程同时调用Recv也没有意义。
/// <para/>所以只需要部分加锁即可。
/// </summary>
/// <param name="writer"></param>
/// <returns></returns>
public int TryRecv(IBufferWriter<byte> writer)
{
var peekSize = -1;
lock (rcv_queueLock)
{
if (rcv_queue.Count == 0)
{
///没有可用包
return -1;
}
var seq = rcv_queue[0];
if (seq.frg == 0)
{
peekSize = (int)seq.len;
}
if (rcv_queue.Count < seq.frg + 1)
{
///没有足够的包
return -1;
}
uint length = 0;
foreach (var item in rcv_queue)
{
length += item.len;
if (item.frg == 0)
{
break;
}
}
peekSize = (int)length;
if (peekSize <= 0)
{
return -2;
}
}
return UncheckRecv(writer);
}
/// <summary>
/// user/upper level recv: returns size, returns below zero for EAGAIN
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
public int Recv(Span<byte> buffer)
{
if (0 == rcv_queue.Count)
{
return -1;
}
var peekSize = PeekSize();
if (peekSize < 0)
{
return -2;
}
if (peekSize > buffer.Length)
{
return -3;
}
/// 拆分函数
var recvLength = UncheckRecv(buffer);
return recvLength;
}
/// <summary>
/// user/upper level recv: returns size, returns below zero for EAGAIN
/// </summary>
/// <param name="writer"></param>
/// <returns></returns>
public int Recv(IBufferWriter<byte> writer)
{
if (0 == rcv_queue.Count)
{
return -1;
}
var peekSize = PeekSize();
if (peekSize < 0)
{
return -2;
}
//if (peekSize > buffer.Length)
//{
// return -3;
//}
/// 拆分函数
var recvLength = UncheckRecv(writer);
return recvLength;
}
/// <summary>
/// 这个函数不检查任何参数
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
int UncheckRecv(Span<byte> buffer)
{
var recover = false;
if (rcv_queue.Count >= rcv_wnd)
{
recover = true;
}
#region merge fragment.
/// merge fragment.
var recvLength = 0;
lock (rcv_queueLock)
{
var count = 0;
foreach (var seg in rcv_queue)
{
seg.data.CopyTo(buffer.Slice(recvLength));
recvLength += (int)seg.len;
count++;
int frg = seg.frg;
SegmentManager.Free(seg);
if (frg == 0)
{
break;
}
}
if (count > 0)
{
rcv_queue.RemoveRange(0, count);
}
}
#endregion
Move_Rcv_buf_2_Rcv_queue();
#region fast recover
/// fast recover
if (rcv_queue.Count < rcv_wnd && recover)
{
// ready to send back IKCP_CMD_WINS in ikcp_flush
// tell remote my window size
probe |= IKCP_ASK_TELL;
}
#endregion
return recvLength;
}
/// <summary>
/// 这个函数不检查任何参数
/// </summary>
/// <param name="writer"></param>
/// <returns></returns>
int UncheckRecv(IBufferWriter<byte> writer)
{
var recover = false;
if (rcv_queue.Count >= rcv_wnd)
{
recover = true;
}
#region merge fragment.
/// merge fragment.
var recvLength = 0;
lock (rcv_queueLock)
{
var count = 0;
foreach (var seg in rcv_queue)
{
var len = (int)seg.len;
var destination = writer.GetSpan(len);
seg.data.CopyTo(destination);
writer.Advance(len);
recvLength += len;
count++;
int frg = seg.frg;
SegmentManager.Free(seg);
if (frg == 0)
{
break;
}
}
if (count > 0)
{
rcv_queue.RemoveRange(0, count);
}
}
#endregion
Move_Rcv_buf_2_Rcv_queue();
#region fast recover
/// fast recover
if (rcv_queue.Count < rcv_wnd && recover)
{
// ready to send back IKCP_CMD_WINS in ikcp_flush
// tell remote my window size
probe |= IKCP_ASK_TELL;
}
#endregion
return recvLength;
}
/// <summary>
/// check the size of next message in the recv queue
/// </summary>
/// <returns></returns>
public int PeekSize()
{
lock (rcv_queueLock)
{
if (rcv_queue.Count == 0)
{
///没有可用包
return -1;
}
var seq = rcv_queue[0];
if (seq.frg == 0)
{
return (int)seq.len;
}
if (rcv_queue.Count < seq.frg + 1)
{
///没有足够的包
return -1;
}
uint length = 0;
foreach (var seg in rcv_queue)
{
length += seg.len;
if (seg.frg == 0)
{
break;
}
}
return (int)length;
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b3840e90e37f0194bbfafb564ff80d45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: fcc0172c723e55a4389ad2f62b68a3fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,262 +0,0 @@
using System.Buffers;
using System.Collections.Generic;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using BufferOwner = System.Buffers.IMemoryOwner<byte>;
namespace System.Net.Sockets.Kcp
{
/// <summary>
/// <inheritdoc cref="IPipe{T}"/>
/// <para></para>这是个简单的实现,更复杂使用微软官方实现<see cref="Channel.CreateBounded{T}(int)"/>
/// </summary>
/// <typeparam name="T"></typeparam>
internal class QueuePipe<T> : Queue<T>
{
readonly object _innerLock = new object();
private TaskCompletionSource<T> source;
//线程同步上下文由Task机制保证无需额外处理
//SynchronizationContext callbackContext;
//public bool UseSynchronizationContext { get; set; } = true;
public virtual void Write(T item)
{
lock (_innerLock)
{
if (source == null)
{
Enqueue(item);
}
else
{
if (Count > 0)
{
throw new Exception("内部顺序错误,不应该出现,请联系作者");
}
var next = source;
source = null;
next.TrySetResult(item);
}
}
}
public new void Enqueue(T item)
{
lock (_innerLock)
{
base.Enqueue(item);
}
}
public void Flush()
{
lock (_innerLock)
{
if (Count > 0)
{
var res = Dequeue();
var next = source;
source = null;
next?.TrySetResult(res);
}
}
}
public virtual Task<T> ReadAsync()
{
lock (_innerLock)
{
if (this.Count > 0)
{
var next = Dequeue();
return Task.FromResult(next);
}
else
{
source = new TaskCompletionSource<T>();
return source.Task;
}
}
}
public UniTask<T> ReadValueTaskAsync()
{
throw new NotImplementedException();
}
}
public class KcpIO<Segment> : KcpCore<Segment>, IKcpIO
where Segment : IKcpSegment
{
OutputQ outq;
public KcpIO(uint conv_) : base(conv_)
{
outq = new OutputQ();
callbackHandle = outq;
}
internal override void Parse_data(Segment newseg)
{
base.Parse_data(newseg);
lock (rcv_queueLock)
{
var recover = false;
if (rcv_queue.Count >= rcv_wnd)
{
recover = true;
}
while (TryRecv(out var arraySegment) > 0)
{
recvSignal.Enqueue(arraySegment);
}
recvSignal.Flush();
#region fast recover
/// fast recover
if (rcv_queue.Count < rcv_wnd && recover)
{
// ready to send back IKCP_CMD_WINS in ikcp_flush
// tell remote my window size
probe |= IKCP_ASK_TELL;
}
#endregion
}
}
QueuePipe<ArraySegment<Segment>> recvSignal = new QueuePipe<ArraySegment<Segment>>();
internal int TryRecv(out ArraySegment<Segment> package)
{
package = default;
lock (rcv_queueLock)
{
var peekSize = -1;
if (rcv_queue.Count == 0)
{
///没有可用包
return -1;
}
var seq = rcv_queue[0];
if (seq.frg == 0)
{
peekSize = (int)seq.len;
}
if (rcv_queue.Count < seq.frg + 1)
{
///没有足够的包
return -1;
}
uint length = 0;
Segment[] kcpSegments = ArrayPool<Segment>.Shared.Rent(seq.frg + 1);
var index = 0;
foreach (var item in rcv_queue)
{
kcpSegments[index] = item;
index++;
length += item.len;
if (item.frg == 0)
{
break;
}
}
if (index > 0)
{
rcv_queue.RemoveRange(0, index);
}
package = new ArraySegment<Segment>(kcpSegments, 0, index);
peekSize = (int)length;
if (peekSize <= 0)
{
return -2;
}
return peekSize;
}
}
public async UniTask RecvAsync(IBufferWriter<byte> writer, object options = null)
{
var arraySegment = await recvSignal.ReadAsync().ConfigureAwait(false);
for (int i = arraySegment.Offset; i < arraySegment.Count; i++)
{
WriteRecv(writer, arraySegment.Array[i]);
}
ArrayPool<Segment>.Shared.Return(arraySegment.Array, true);
}
private void WriteRecv(IBufferWriter<byte> writer, Segment seg)
{
var curCount = (int)seg.len;
var target = writer.GetSpan(curCount);
seg.data.CopyTo(target);
SegmentManager.Free(seg);
writer.Advance(curCount);
}
public async UniTask<int> RecvAsync(ArraySegment<byte> buffer, object options = null)
{
var arraySegment = await recvSignal.ReadAsync().ConfigureAwait(false);
int start = buffer.Offset;
for (int i = arraySegment.Offset; i < arraySegment.Count; i++)
{
var target = new Memory<byte>(buffer.Array, start, buffer.Array.Length - start);
var seg = arraySegment.Array[i];
seg.data.CopyTo(target.Span);
start += seg.data.Length;
SegmentManager.Free(seg);
}
ArrayPool<Segment>.Shared.Return(arraySegment.Array, true);
return start - buffer.Offset;
}
public async UniTask OutputAsync(IBufferWriter<byte> writer, object options = null)
{
var (Owner, Count) = await outq.ReadAsync().ConfigureAwait(false);
WriteOut(writer, Owner, Count);
}
private static void WriteOut(IBufferWriter<byte> writer, BufferOwner Owner, int Count)
{
var target = writer.GetSpan(Count);
Owner.Memory.Span.Slice(0, Count).CopyTo(target);
writer.Advance(Count);
Owner.Dispose();
}
protected internal override BufferOwner CreateBuffer(int needSize)
{
return MemoryPool<byte>.Shared.Rent(needSize);
}
internal class OutputQ : QueuePipe<(BufferOwner Owner, int Count)>,
IKcpCallback
{
public void Output(BufferOwner buffer, int avalidLength)
{
Write((buffer, avalidLength));
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3c30d30fa46372948b60bd56eec47fe6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,50 +0,0 @@
using System.Buffers;
namespace System.Net.Sockets.Kcp
{
public abstract class KcpOutputWriter : IKcpOutputWriter
{
public int UnflushedBytes { get; set; }
public IMemoryOwner<byte> MemoryOwner { get; set; }
public void Flush()
{
Output(MemoryOwner, UnflushedBytes);
MemoryOwner = null;
UnflushedBytes = 0;
}
public void Advance(int count)
{
UnflushedBytes += count;
}
public Memory<byte> GetMemory(int sizeHint = 0)
{
if (MemoryOwner == null)
{
MemoryOwner = MemoryPool<byte>.Shared.Rent(2048);
}
return MemoryOwner.Memory.Slice(UnflushedBytes);
}
public Span<byte> GetSpan(int sizeHint = 0)
{
if (MemoryOwner == null)
{
MemoryOwner = MemoryPool<byte>.Shared.Rent(2048);
}
return MemoryOwner.Memory.Span.Slice(UnflushedBytes);
}
/// <summary>
/// Socket发送是要pin byte[],为了不阻塞KcpFlush动态缓存是必须的。
/// </summary>
/// <param name="buffer"></param>
/// <param name="avalidLength"></param>
public abstract void Output(IMemoryOwner<byte> buffer, int avalidLength);
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a058d8fa8a92dc94395bfd6e1f6fdb8f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,402 +0,0 @@
using System.Buffers.Binary;
using System.Runtime.InteropServices;
namespace System.Net.Sockets.Kcp
{
/// <summary>
/// 调整了没存布局,直接拷贝块提升性能。
/// <para>结构体保存内容只有一个指针,不用担心参数传递过程中的性能</para>
/// https://github.com/skywind3000/kcp/issues/118#issuecomment-338133930
/// <para>不要对没有初始化的KcpSegment(内部指针为0所有属性都将指向位置区域) 进行任何赋值操作,可能导致内存损坏。
/// 出于性能考虑,没有对此项进行安全检查。</para>
/// </summary>
public struct KcpSegment : IKcpSegment
{
internal readonly unsafe byte* ptr;
public unsafe KcpSegment(byte* intPtr, uint appendDateSize)
{
this.ptr = intPtr;
len = appendDateSize;
}
/// <summary>
/// 使用完必须显示释放,否则内存泄漏
/// </summary>
/// <param name="appendDateSize"></param>
/// <returns></returns>
public static KcpSegment AllocHGlobal(int appendDateSize)
{
var total = LocalOffset + HeadOffset + appendDateSize;
IntPtr intPtr = Marshal.AllocHGlobal(total);
unsafe
{
///清零 不知道是不是有更快的清0方法
Span<byte> span = new Span<byte>(intPtr.ToPointer(), total);
span.Clear();
return new KcpSegment((byte*)intPtr.ToPointer(), (uint)appendDateSize);
}
}
/// <summary>
/// 释放非托管内存
/// </summary>
/// <param name="seg"></param>
public static void FreeHGlobal(KcpSegment seg)
{
unsafe
{
Marshal.FreeHGlobal((IntPtr)seg.ptr);
}
}
/// 以下为本机使用的参数
/// <summary>
/// offset = 0
/// </summary>
public uint resendts
{
get
{
unsafe
{
return *(uint*)(ptr + 0);
}
}
set
{
unsafe
{
*(uint*)(ptr + 0) = value;
}
}
}
/// <summary>
/// offset = 4
/// </summary>
public uint rto
{
get
{
unsafe
{
return *(uint*)(ptr + 4);
}
}
set
{
unsafe
{
*(uint*)(ptr + 4) = value;
}
}
}
/// <summary>
/// offset = 8
/// </summary>
public uint fastack
{
get
{
unsafe
{
return *(uint*)(ptr + 8);
}
}
set
{
unsafe
{
*(uint*)(ptr + 8) = value;
}
}
}
/// <summary>
/// offset = 12
/// </summary>
public uint xmit
{
get
{
unsafe
{
return *(uint*)(ptr + 12);
}
}
set
{
unsafe
{
*(uint*)(ptr + 12) = value;
}
}
}
///以下为需要网络传输的参数
public const int LocalOffset = 4 * 4;
public const int HeadOffset = KcpConst.IKCP_OVERHEAD;
/// <summary>
/// offset = <see cref="LocalOffset"/>
/// </summary>
/// https://github.com/skywind3000/kcp/issues/134
public uint conv
{
get
{
unsafe
{
return *(uint*)(LocalOffset + 0 + ptr);
}
}
set
{
unsafe
{
*(uint*)(LocalOffset + 0 + ptr) = value;
}
}
}
/// <summary>
/// offset = <see cref="LocalOffset"/> + 4
/// </summary>
public byte cmd
{
get
{
unsafe
{
return *(LocalOffset + 4 + ptr);
}
}
set
{
unsafe
{
*(LocalOffset + 4 + ptr) = value;
}
}
}
/// <summary>
/// offset = <see cref="LocalOffset"/> + 5
/// </summary>
public byte frg
{
get
{
unsafe
{
return *(LocalOffset + 5 + ptr);
}
}
set
{
unsafe
{
*(LocalOffset + 5 + ptr) = value;
}
}
}
/// <summary>
/// offset = <see cref="LocalOffset"/> + 6
/// </summary>
public ushort wnd
{
get
{
unsafe
{
return *(ushort*)(LocalOffset + 6 + ptr);
}
}
set
{
unsafe
{
*(ushort*)(LocalOffset + 6 + ptr) = value;
}
}
}
/// <summary>
/// offset = <see cref="LocalOffset"/> + 8
/// </summary>
public uint ts
{
get
{
unsafe
{
return *(uint*)(LocalOffset + 8 + ptr);
}
}
set
{
unsafe
{
*(uint*)(LocalOffset + 8 + ptr) = value;
}
}
}
/// <summary>
/// <para> SendNumber? </para>
/// offset = <see cref="LocalOffset"/> + 12
/// </summary>
public uint sn
{
get
{
unsafe
{
return *(uint*)(LocalOffset + 12 + ptr);
}
}
set
{
unsafe
{
*(uint*)(LocalOffset + 12 + ptr) = value;
}
}
}
/// <summary>
/// offset = <see cref="LocalOffset"/> + 16
/// </summary>
public uint una
{
get
{
unsafe
{
return *(uint*)(LocalOffset + 16 + ptr);
}
}
set
{
unsafe
{
*(uint*)(LocalOffset + 16 + ptr) = value;
}
}
}
/// <summary>
/// <para> AppendDateSize </para>
/// offset = <see cref="LocalOffset"/> + 20
/// </summary>
public uint len
{
get
{
unsafe
{
return *(uint*)(LocalOffset + 20 + ptr);
}
}
private set
{
unsafe
{
*(uint*)(LocalOffset + 20 + ptr) = value;
}
}
}
/// <summary>
///
/// </summary>
/// https://github.com/skywind3000/kcp/issues/35#issuecomment-263770736
public Span<byte> data
{
get
{
unsafe
{
return new Span<byte>(LocalOffset + HeadOffset + ptr, (int)len);
}
}
}
/// <summary>
/// 将片段中的要发送的数据拷贝到指定缓冲区
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
public int Encode(Span<byte> buffer)
{
var datelen = (int)(HeadOffset + len);
///备用偏移值 现阶段没有使用
const int offset = 0;
if (KcpConst.IsLittleEndian)
{
if (BitConverter.IsLittleEndian)
{
///小端可以一次拷贝
unsafe
{
///要发送的数据从LocalOffset开始。
///本结构体调整了要发送字段和单机使用字段的位置,让报头数据和数据连续,节约一次拷贝。
Span<byte> sendDate = new Span<byte>(ptr + LocalOffset, datelen);
sendDate.CopyTo(buffer);
}
}
else
{
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), conv);
buffer[offset + 4] = cmd;
buffer[offset + 5] = frg;
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 6), wnd);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 8), ts);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 12), sn);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 16), una);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 20), len);
data.CopyTo(buffer.Slice(HeadOffset));
}
}
else
{
if (BitConverter.IsLittleEndian)
{
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset), conv);
buffer[offset + 4] = cmd;
buffer[offset + 5] = frg;
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(offset + 6), wnd);
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 8), ts);
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 12), sn);
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 16), una);
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 20), len);
data.CopyTo(buffer.Slice(HeadOffset));
}
else
{
///大端可以一次拷贝
unsafe
{
///要发送的数据从LocalOffset开始。
///本结构体调整了要发送字段和单机使用字段的位置,让报头数据和数据连续,节约一次拷贝。
Span<byte> sendDate = new Span<byte>(ptr + LocalOffset, datelen);
sendDate.CopyTo(buffer);
}
}
}
return datelen;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: daab08fc1f00355429c23a1e36993942
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,79 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace System.Net.Sockets.Kcp
{
public partial class KcpCore<Segment>
{
public KcpLogMask LogMask { get; set; } = KcpLogMask.IKCP_LOG_PARSE_DATA | KcpLogMask.IKCP_LOG_NEED_SEND | KcpLogMask.IKCP_LOG_DEAD_LINK;
public virtual bool CanLog(KcpLogMask mask)
{
if ((mask & LogMask) == 0)
{
return false;
}
#if NETSTANDARD2_0_OR_GREATER || NET5_0_OR_GREATER
if (TraceListener != null)
{
return true;
}
#endif
return false;
}
#if NETSTANDARD2_0_OR_GREATER || NET5_0_OR_GREATER
public System.Diagnostics.TraceListener TraceListener { get; set; }
#endif
public virtual void LogFail(string message)
{
#if NETSTANDARD2_0_OR_GREATER || NET5_0_OR_GREATER
TraceListener?.Fail(message);
#endif
}
public virtual void LogWriteLine(string message, string category)
{
#if NETSTANDARD2_0_OR_GREATER || NET5_0_OR_GREATER
TraceListener?.WriteLine(message, category);
#endif
}
[Obsolete("一定要先判断CanLog 内部判断是否存在TraceListener,避免在没有TraceListener时生成字符串", true)]
public virtual void LogWriteLine(string message, KcpLogMask mask)
{
#if NETSTANDARD2_0_OR_GREATER || NET5_0_OR_GREATER
if (CanLog(mask))
{
LogWriteLine(message, mask.ToString());
}
#endif
}
}
[Flags]
public enum KcpLogMask
{
IKCP_LOG_OUTPUT = 1 << 0,
IKCP_LOG_INPUT = 1 << 1,
IKCP_LOG_SEND = 1 << 2,
IKCP_LOG_RECV = 1 << 3,
IKCP_LOG_IN_DATA = 1 << 4,
IKCP_LOG_IN_ACK = 1 << 5,
IKCP_LOG_IN_PROBE = 1 << 6,
IKCP_LOG_IN_WINS = 1 << 7,
IKCP_LOG_OUT_DATA = 1 << 8,
IKCP_LOG_OUT_ACK = 1 << 9,
IKCP_LOG_OUT_PROBE = 1 << 10,
IKCP_LOG_OUT_WINS = 1 << 11,
IKCP_LOG_PARSE_DATA = 1 << 12,
IKCP_LOG_NEED_SEND = 1 << 13,
IKCP_LOG_DEAD_LINK = 1 << 14,
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 39791b0c45bf4864e87385c477d9b50c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,265 +0,0 @@
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Buffers.Binary;
namespace System.Net.Sockets.Kcp
{
/// <summary>
/// 动态申请非托管内存
/// </summary>
public class SimpleSegManager : ISegmentManager<KcpSegment>
{
public static SimpleSegManager Default { get; } = new SimpleSegManager();
public KcpSegment Alloc(int appendDateSize)
{
return KcpSegment.AllocHGlobal(appendDateSize);
}
public void Free(KcpSegment seg)
{
KcpSegment.FreeHGlobal(seg);
}
public class Kcp : Kcp<KcpSegment>
{
public Kcp(uint conv_, IKcpCallback callback, IRentable rentable = null)
: base(conv_, callback, rentable)
{
SegmentManager = Default;
}
}
public class KcpIO : KcpIO<KcpSegment>
{
public KcpIO(uint conv_)
: base(conv_)
{
SegmentManager = Default;
}
}
}
/// <summary>
/// 申请固定大小非托管内存。使用这个就不能SetMtu了大小已经写死。
/// </summary>
/// <remarks>需要大量测试</remarks>
public unsafe class UnSafeSegManager : ISegmentManager<KcpSegment>
{
public static UnSafeSegManager Default { get; } = new UnSafeSegManager();
/// <summary>
/// 因为默认mtu是1400并且内存需要内存行/内存页对齐。这里直接512对齐。
/// </summary>
public const int blockSize = 512 * 3;
public HashSet<IntPtr> header = new HashSet<IntPtr>();
public Stack<IntPtr> blocks = new Stack<IntPtr>();
public readonly object locker = new object();
public UnSafeSegManager()
{
Alloc();
}
void Alloc()
{
int count = 50;
IntPtr intPtr = Marshal.AllocHGlobal(blockSize * count);
header.Add(intPtr);
for (int i = 0; i < count; i++)
{
blocks.Push(intPtr + blockSize * i);
}
}
~UnSafeSegManager()
{
foreach (var item in header)
{
Marshal.FreeHGlobal(item);
}
}
public KcpSegment Alloc(int appendDateSize)
{
lock (locker)
{
var total = KcpSegment.LocalOffset + KcpSegment.HeadOffset + appendDateSize;
if (total > blockSize)
{
throw new ArgumentOutOfRangeException();
}
if (blocks.Count > 0)
{
}
else
{
Alloc();
}
var ptr = blocks.Pop();
Span<byte> span = new Span<byte>(ptr.ToPointer(), blockSize);
span.Clear();
return new KcpSegment((byte*)ptr.ToPointer(), (uint)appendDateSize);
}
}
public void Free(KcpSegment seg)
{
IntPtr ptr = (IntPtr)seg.ptr;
blocks.Push(ptr);
}
public class Kcp : Kcp<KcpSegment>
{
public Kcp(uint conv_, IKcpCallback callback, IRentable rentable = null)
: base(conv_, callback, rentable)
{
SegmentManager = Default;
}
}
public class KcpIO : KcpIO<KcpSegment>
{
public KcpIO(uint conv_)
: base(conv_)
{
SegmentManager = Default;
}
}
}
/// <summary>
/// 使用内存池而不是非托管内存有内存alloc但是不多。可以解决Marshal.AllocHGlobal 内核调用带来的性能问题
/// </summary>
public class PoolSegManager : ISegmentManager<PoolSegManager.Seg>
{
public static PoolSegManager Default { get; } = new PoolSegManager();
/// <summary>
/// 因为默认mtu是1400并且内存需要内存行/内存页对齐。这里直接512对齐。
/// </summary>
public const int blockSize = 512 * 3;
public class Seg : IKcpSegment
{
byte[] cache;
public Seg(int blockSize)
{
cache = Buffers.ArrayPool<byte>.Shared.Rent(blockSize);
}
///以下为需要网络传输的参数
public const int LocalOffset = 4 * 4;
public const int HeadOffset = Kcp.IKCP_OVERHEAD;
public byte cmd { get; set; }
public uint conv { get; set; }
public Span<byte> data => cache.AsSpan().Slice(0, (int)len);
public uint fastack { get; set; }
public byte frg { get; set; }
public uint len { get; internal set; }
public uint resendts { get; set; }
public uint rto { get; set; }
public uint sn { get; set; }
public uint ts { get; set; }
public uint una { get; set; }
public ushort wnd { get; set; }
public uint xmit { get; set; }
public int Encode(Span<byte> buffer)
{
var datelen = (int)(HeadOffset + len);
///备用偏移值 现阶段没有使用
const int offset = 0;
if (BitConverter.IsLittleEndian)
{
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), conv);
buffer[offset + 4] = cmd;
buffer[offset + 5] = frg;
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 6), wnd);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 8), ts);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 12), sn);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 16), una);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 20), len);
data.CopyTo(buffer.Slice(HeadOffset));
}
else
{
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset), conv);
buffer[offset + 4] = cmd;
buffer[offset + 5] = frg;
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(offset + 6), wnd);
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 8), ts);
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 12), sn);
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 16), una);
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 20), len);
data.CopyTo(buffer.Slice(HeadOffset));
}
return datelen;
}
}
ConcurrentStack<Seg> Pool = new ConcurrentStack<Seg>();
public Seg Alloc(int appendDateSize)
{
if (appendDateSize > blockSize)
{
throw new NotSupportedException();
}
if (Pool.TryPop(out var ret))
{
}
else
{
ret = new Seg(blockSize);
}
ret.len = (uint)appendDateSize;
return ret;
}
public void Free(Seg seg)
{
seg.cmd = 0;
seg.conv = 0;
seg.fastack = 0;
seg.frg = 0;
seg.len = 0;
seg.resendts = 0;
seg.rto = 0;
seg.sn = 0;
seg.ts = 0;
seg.una = 0;
seg.wnd = 0;
seg.xmit = 0;
Pool.Push(seg);
}
public class Kcp : Kcp<Seg>
{
public Kcp(uint conv_, IKcpCallback callback, IRentable rentable = null)
: base(conv_, callback, rentable)
{
SegmentManager = Default;
}
}
public class KcpIO : KcpIO<Seg>
{
public KcpIO(uint conv_)
: base(conv_)
{
SegmentManager = Default;
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e7f0d71aa1362b6488c3173d525fd284
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,65 +0,0 @@
using System.Buffers;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
namespace System.Net.Sockets.Kcp.Simple
{
/// <summary>
/// 简单例子。
/// </summary>
public class SimpleKcpClient : IKcpCallback
{
UdpClient client;
public SimpleKcpClient(int port)
: this(port, null)
{
}
public SimpleKcpClient(int port, IPEndPoint endPoint)
{
client = new UdpClient(port);
kcp = new SimpleSegManager.Kcp(2001, this);
this.EndPoint = endPoint;
BeginRecv();
}
public SimpleSegManager.Kcp kcp { get; }
public IPEndPoint EndPoint { get; set; }
public void Output(IMemoryOwner<byte> buffer, int avalidLength)
{
var s = buffer.Memory.Span.Slice(0, avalidLength).ToArray();
client.SendAsync(s, s.Length, EndPoint);
buffer.Dispose();
}
public void SendAsync(byte[] datagram, int bytes)
{
kcp.Send(datagram.AsSpan().Slice(0, bytes));
}
public async UniTask<byte[]> ReceiveAsync()
{
var (buffer, avalidLength) = kcp.TryRecv();
while (buffer == null)
{
await Task.Delay(10);
(buffer, avalidLength) = kcp.TryRecv();
}
var s = buffer.Memory.Span.Slice(0, avalidLength).ToArray();
return s;
}
private async void BeginRecv()
{
var res = await client.ReceiveAsync();
EndPoint = res.RemoteEndPoint;
kcp.Input(res.Buffer);
BeginRecv();
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: ff16ed9b89525df4aa6501c0edc679d5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,48 +0,0 @@
using System.Net.Sockets.Kcp.Simple;
using System.Threading.Tasks;
namespace System.Net.Sockets.Kcp
{
namespace TestServer
{
/// <summary>
/// 简单例子。
/// </summary>
class SimpleKcpServer
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
SimpleKcpClient kcpClient = new SimpleKcpClient(40001);
Task.Run(async () =>
{
while (true)
{
kcpClient.kcp.Update(DateTimeOffset.UtcNow);
await Task.Delay(10);
}
});
StartRecv(kcpClient);
Console.ReadLine();
}
static async void StartRecv(SimpleKcpClient client)
{
while (true)
{
var res = await client.ReceiveAsync();
var str = System.Text.Encoding.UTF8.GetString(res);
if ("发送一条消息" == str)
{
Console.WriteLine(str);
var buffer = System.Text.Encoding.UTF8.GetBytes("回复一条消息");
client.SendAsync(buffer, buffer.Length);
}
}
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 97e221b7388e412da59b0f4d200cb891
timeCreated: 1682095200

View File

@@ -1,73 +0,0 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
//[assembly: InternalsVisibleTo("UnitTestProject1")]
namespace System.Net.Sockets.Kcp
{
public static class KcpExtension_FDF71D0BC31D49C48EEA8FAA51F017D4
{
private static readonly DateTime utc_time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
[Obsolete("", true)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ConvertTime(this in DateTime time)
{
return (uint)(Convert.ToInt64(time.Subtract(utc_time).TotalMilliseconds) & 0xffffffff);
}
private static readonly DateTimeOffset utc1970 = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ConvertTimeOld(this in DateTimeOffset time)
{
return (uint)(Convert.ToInt64(time.Subtract(utc1970).TotalMilliseconds) & 0xffffffff);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ConvertTime2(this in DateTimeOffset time)
{
#if NETSTANDARD2_0_OR_GREATER || NET5_0_OR_GREATER
return (uint)(time.ToUnixTimeMilliseconds() & 0xffffffff);
#else
return (uint)(Convert.ToInt64(time.Subtract(utc1970).TotalMilliseconds) & 0xffffffff);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ConvertTime(this in DateTimeOffset time)
{
#if NETSTANDARD2_0_OR_GREATER || NET5_0_OR_GREATER
return (uint)(time.ToUnixTimeMilliseconds());
#else
return (uint)(Convert.ToInt64(time.Subtract(utc1970).TotalMilliseconds) & 0xffffffff);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToLogString<T>(this T segment, bool local = false)
where T : IKcpSegment
{
if (local)
{
return $"sn:{segment.sn,2} una:{segment.una,2} frg:{segment.frg,2} cmd:{segment.cmd,2} len:{segment.len,2} wnd:{segment.wnd} [ LocalValue: xmit:{segment.xmit} fastack:{segment.fastack} rto:{segment.rto} ]";
}
else
{
return $"sn:{segment.sn,2} una:{segment.una,2} frg:{segment.frg,2} cmd:{segment.cmd,2} len:{segment.len,2} wnd:{segment.wnd}";
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Encode<T>(this T Seg, IBufferWriter<byte> writer)
where T : IKcpSegment
{
var totalLength = (int)(KcpSegment.HeadOffset + Seg.len);
var span = writer.GetSpan(totalLength);
Seg.Encode(span);
writer.Advance(totalLength);
return totalLength;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: cd298c4aa310a7e448c4694ddc41337e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,287 +0,0 @@
using System;
using System.Net;
using System.Net.Sockets;
namespace TEngine
{
internal sealed partial class NetworkManager
{
/// <summary>
/// Kcp 网络频道。
/// </summary>
private sealed class KcpNetworkChannel : NetworkChannelBase
{
private readonly AsyncCallback _connectCallback;
private readonly AsyncCallback _sendCallback;
private readonly AsyncCallback _receiveCallback;
/// <summary>
/// 获取网络服务类型。
/// </summary>
public override ServiceType ServiceType => ServiceType.Kcp;
public KcpNetworkChannel(string name, INetworkChannelHelper networkChannelHelper)
: base(name, networkChannelHelper)
{
_connectCallback = ConnectCallback;
_sendCallback = SendCallback;
_receiveCallback = ReceiveCallback;
}
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
/// <param name="userData">用户自定义数据。</param>
public override void Connect(IPAddress ipAddress, int port, object userData)
{
base.Connect(ipAddress, port, userData);
MSocket = new Socket(ipAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
if (MSocket == null)
{
string errorMessage = "Initialize network channel failure.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.SocketError, SocketError.Success, errorMessage);
return;
}
throw new GameFrameworkException(errorMessage);
}
NetworkChannelHelper.PrepareForConnecting();
ConnectAsync(ipAddress, port, userData);
}
private void ConnectAsync(IPAddress ipAddress, int port, object userData)
{
try
{
MSocket.BeginConnect(ipAddress, port, _connectCallback, new ConnectState(MSocket, userData));
}
catch (Exception exception)
{
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ConnectError,
socketException?.SocketErrorCode ?? SocketError.Success,
exception.ToString());
return;
}
throw;
}
}
protected override bool ProcessSend()
{
if (base.ProcessSend())
{
SendAsync();
return true;
}
return false;
}
private void ConnectCallback(IAsyncResult ar)
{
ConnectState socketUserData = (ConnectState)ar.AsyncState;
try
{
socketUserData.Socket.EndConnect(ar);
}
catch (ObjectDisposedException)
{
return;
}
catch (Exception exception)
{
Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ConnectError,
socketException?.SocketErrorCode ?? SocketError.Success,
exception.ToString());
return;
}
throw;
}
MSentPacketCount = 0;
MReceivedPacketCount = 0;
lock (SendPacketPool)
{
SendPacketPool.Clear();
}
lock (MHeartBeatState)
{
MHeartBeatState.Reset(true);
}
if (NetworkChannelConnected != null)
{
NetworkChannelConnected(this, socketUserData.UserData);
}
Active = true;
ReceiveAsync();
}
private void SendAsync()
{
try
{
MSocket.BeginSend(MSendState.Stream.GetBuffer(), (int)MSendState.Stream.Position,
(int)(MSendState.Stream.Length - MSendState.Stream.Position), SocketFlags.None, _sendCallback,
MSocket);
}
catch (Exception exception)
{
Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SendError,
socketException?.SocketErrorCode ?? SocketError.Success,
exception.ToString());
return;
}
throw;
}
}
private void SendCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
if (!socket.Connected)
{
return;
}
int bytesSent = 0;
try
{
bytesSent = socket.EndSend(ar);
}
catch (Exception exception)
{
Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SendError,
socketException?.SocketErrorCode ?? SocketError.Success,
exception.ToString());
return;
}
throw;
}
MSendState.Stream.Position += bytesSent;
if (MSendState.Stream.Position < MSendState.Stream.Length)
{
SendAsync();
return;
}
MSentPacketCount++;
MSendState.Reset();
}
private void ReceiveAsync()
{
try
{
MSocket.BeginReceive(MReceiveState.Stream.GetBuffer(), (int)MReceiveState.Stream.Position,
(int)(MReceiveState.Stream.Length - MReceiveState.Stream.Position), SocketFlags.None,
_receiveCallback, MSocket);
}
catch (Exception exception)
{
Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ReceiveError,
socketException?.SocketErrorCode ?? SocketError.Success,
exception.ToString());
return;
}
throw;
}
}
private void ReceiveCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
if (!socket.Connected)
{
return;
}
int bytesReceived = 0;
try
{
bytesReceived = socket.EndReceive(ar);
}
catch (Exception exception)
{
Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ReceiveError,
socketException?.SocketErrorCode ?? SocketError.Success,
exception.ToString());
return;
}
throw;
}
if (bytesReceived <= 0)
{
Close();
return;
}
MReceiveState.Stream.Position += bytesReceived;
if (MReceiveState.Stream.Position < MReceiveState.Stream.Length)
{
ReceiveAsync();
return;
}
MReceiveState.Stream.Position = 0L;
bool processSuccess = false;
if (MReceiveState.PacketHeader != null)
{
processSuccess = ProcessPacket();
MReceivedPacketCount++;
}
else
{
processSuccess = ProcessPacketHeader();
}
if (processSuccess)
{
ReceiveAsync();
}
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 70ff4fca885c401ea776223622deab75
timeCreated: 1682092071

View File

@@ -1,54 +0,0 @@
using System.Net;
using System.Net.Sockets;
namespace TEngine
{
public class NetUtil
{
public static bool IsHaveIpV6Address(IPAddress[] ipAddresses, ref IPAddress[] outIPs)
{
int v6Count = 0;
for (int i = 0; i < ipAddresses.Length; i++)
{
if (System.Net.Sockets.AddressFamily.InterNetworkV6.Equals(ipAddresses[i].AddressFamily))
{
v6Count++;
}
}
if (v6Count > 0)
{
outIPs = new IPAddress[v6Count];
int resIndex = 0;
for (int i = 0; i < ipAddresses.Length; i++)
{
if (System.Net.Sockets.AddressFamily.InterNetworkV6.Equals(ipAddresses[i].AddressFamily))
{
outIPs[resIndex++] = ipAddresses[i];
}
}
return true;
}
return false;
}
public static IPEndPoint GetEndPoint(string server, int port)
{
IPAddress[] ps = Dns.GetHostAddresses(server);
IPAddress[] finalIps = ps;
if (Socket.OSSupportsIPv6 && NetUtil.IsHaveIpV6Address(ps, ref finalIps))
{
Log.Error("socket use addr ipV6: {0}, IP count:{1} AddressFamily[{2}]", server, finalIps.Length, finalIps[0].AddressFamily);
}
if (finalIps.Length > 0)
{
return new IPEndPoint(finalIps[0], port);
}
return null;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 26846cca9e0f4d3c965d58882c1b503e
timeCreated: 1681991073

View File

@@ -1,144 +0,0 @@
using System.Collections.Generic;
using System.Net.Sockets;
using GameBase;
using UnityEngine;
namespace TEngine
{
/// <summary>
/// 网络组件。
/// </summary>
[DisallowMultipleComponent]
public sealed class Network : UnitySingleton<Network>
{
private NetworkManager m_NetworkManager = null;
/// <summary>
/// 获取网络频道数量。
/// </summary>
public int NetworkChannelCount => m_NetworkManager.NetworkChannelCount;
/// <summary>
/// 游戏框架组件初始化。
/// </summary>
public override void Awake()
{
base.Awake();
// m_NetworkManager = GameFrameworkEntry.GetModule<INetworkManager>();
m_NetworkManager = new NetworkManager();
if (m_NetworkManager == null)
{
Log.Fatal("Network manager is invalid.");
return;
}
m_NetworkManager.NetworkConnected += OnNetworkConnected;
m_NetworkManager.NetworkClosed += OnNetworkClosed;
m_NetworkManager.NetworkMissHeartBeat += OnNetworkMissHeartBeat;
m_NetworkManager.NetworkError += OnNetworkError;
m_NetworkManager.NetworkCustomError += OnNetworkCustomError;
}
private void Update()
{
m_NetworkManager.Update(GameTime.deltaTime, GameTime.unscaledDeltaTime);
}
/// <summary>
/// 检查是否存在网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否存在网络频道。</returns>
public bool HasNetworkChannel(string name)
{
return m_NetworkManager.HasNetworkChannel(name);
}
/// <summary>
/// 获取网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>要获取的网络频道。</returns>
public INetworkChannel GetNetworkChannel(string name)
{
return m_NetworkManager.GetNetworkChannel(name);
}
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <returns>所有网络频道。</returns>
public INetworkChannel[] StaticGetAllNetworkChannels()
{
return m_NetworkManager.GetAllNetworkChannels();
}
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <returns>所有网络频道。</returns>
public INetworkChannel[] GetAllNetworkChannels()
{
return m_NetworkManager.GetAllNetworkChannels();
}
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <param name="results">所有网络频道。</param>
public void GetAllNetworkChannels(List<INetworkChannel> results)
{
m_NetworkManager.GetAllNetworkChannels(results);
}
/// <summary>
/// 创建网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="serviceType">网络服务类型。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
/// <returns>要创建的网络频道。</returns>
public INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType,
INetworkChannelHelper networkChannelHelper)
{
return m_NetworkManager.CreateNetworkChannel(name, serviceType, networkChannelHelper);
}
/// <summary>
/// 销毁网络频道。
/// </summary>
/// <param name="channelName">网络频道名称。</param>
/// <returns>是否销毁网络频道成功。</returns>
public bool DestroyNetworkChannel(string channelName)
{
return m_NetworkManager.DestroyNetworkChannel(channelName);
}
private void OnNetworkConnected(INetworkChannel channel, object userdata)
{
GameEvent.Send(NetworkEvent.NetworkConnectedEvent, channel, userdata);
}
private void OnNetworkClosed(INetworkChannel channel)
{
GameEvent.Send(NetworkEvent.NetworkClosedEvent, channel);
}
private void OnNetworkMissHeartBeat(INetworkChannel channel, int missCount)
{
GameEvent.Send(NetworkEvent.NetworkMissHeartBeatEvent, channel, missCount);
}
private void OnNetworkError(INetworkChannel channel, NetworkErrorCode networkErrorCode, SocketError socketError,
string errorMessage)
{
GameEvent.Send(NetworkEvent.NetworkErrorEvent, channel, networkErrorCode, socketError, errorMessage);
}
private void OnNetworkCustomError(INetworkChannel channel, object userData)
{
GameEvent.Send(NetworkEvent.NetworkCustomErrorEvent, channel, userData);
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 8edbc7d090fd4bb1ad2c6aa967ff0b76
timeCreated: 1682044812

View File

@@ -1,53 +0,0 @@
namespace TEngine
{
/// <summary>
/// 网络错误码。
/// </summary>
public enum NetworkErrorCode : byte
{
/// <summary>
/// 未知错误。
/// </summary>
Unknown = 0,
/// <summary>
/// 地址族错误。
/// </summary>
AddressFamilyError,
/// <summary>
/// Socket 错误。
/// </summary>
SocketError,
/// <summary>
/// 连接错误。
/// </summary>
ConnectError,
/// <summary>
/// 发送错误。
/// </summary>
SendError,
/// <summary>
/// 接收错误。
/// </summary>
ReceiveError,
/// <summary>
/// 序列化错误。
/// </summary>
SerializeError,
/// <summary>
/// 反序列化消息包头错误。
/// </summary>
DeserializePacketHeaderError,
/// <summary>
/// 反序列化消息包错误。
/// </summary>
DeserializePacketError
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 0bb8ca2ece7d49d28b1b4fd1bfa027e6
timeCreated: 1681993877

View File

@@ -1,30 +0,0 @@
namespace TEngine
{
public class NetworkEvent
{
/// <summary>
/// 网网络连接成功事件。
/// </summary>
public static int NetworkConnectedEvent = StringId.StringToHash("NetworkEvent.NetworkConnectedEvent");
/// <summary>
/// 网络连接关闭事件。
/// </summary>
public static int NetworkClosedEvent = StringId.StringToHash("NetworkEvent.NetworkClosedEvent");
/// <summary>
/// 网络错误事件。
/// </summary>
public static int NetworkErrorEvent = StringId.StringToHash("NetworkEvent.NetworkErrorEvent");
/// <summary>
/// 用户自定义网络错误事件。
/// </summary>
public static int NetworkCustomErrorEvent = StringId.StringToHash("NetworkEvent.NetworkCustomErrorEvent");
/// <summary>
/// 网络心跳包丢失事件。
/// </summary>
public static int NetworkMissHeartBeatEvent = StringId.StringToHash("NetworkEvent.NetworkMissHeartBeatEvent");
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 8e3b5eb5b76244498181c6117f0e0b1a
timeCreated: 1681993978

View File

@@ -1,23 +0,0 @@
using System.Net.Sockets;
namespace TEngine
{
internal sealed partial class NetworkManager
{
private sealed class ConnectState
{
private readonly Socket _socket;
private readonly object _userData;
public ConnectState(Socket socket, object userData)
{
_socket = socket;
_userData = userData;
}
public Socket Socket => _socket;
public object UserData => _userData;
}
}
}

Some files were not shown because too many files have changed in this diff Show More