<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Yonagi&apos;s World</title><description>Yonagi&apos;s World</description><link>https://www.yonagi.world/</link><language>zh_CN</language><item><title>SFC：基于自定义 .sy 格式的文件归档工具</title><link>https://www.yonagi.world/posts/sfc-project-intro/</link><guid isPermaLink="true">https://www.yonagi.world/posts/sfc-project-intro/</guid><description>Windows 归档工具，围绕 .sy 协议、目录块、偏移量和 UTF-8 路径实现 Huffman 压缩、AES 加密、CLI 与 Qt GUI。</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;项目仓库：
&lt;a href=&quot;https://gitee.com/fifseason/We_compress&quot;&gt;Gitee&lt;/a&gt; | &lt;a href=&quot;https://github.com/KAIDO-YONAGI/Noobs-Compressor&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;SFC（Simple Files Compressor）面向 Windows，输出格式为自定义 &lt;code&gt;.sy&lt;/code&gt;。项目围绕归档协议、目录块写入、偏移量维护、路径编码转换和压缩加密组合展开。CLI 与 Qt GUI 共用核心层，界面层负责参数、进度和线程调度。&lt;/p&gt;
&lt;h2&gt;对象&lt;/h2&gt;
&lt;p&gt;工程对象分成协议层、目录层、数据层、界面层。协议层由 &lt;code&gt;HeaderWriter&lt;/code&gt;、&lt;code&gt;Locator&lt;/code&gt;、&lt;code&gt;BinaryStandardLoader&lt;/code&gt;、&lt;code&gt;EntryParser&lt;/code&gt; 组成，核心字段包括 &lt;code&gt;strategy&lt;/code&gt;、&lt;code&gt;version&lt;/code&gt;、&lt;code&gt;directoryOffset&lt;/code&gt;、&lt;code&gt;compressedSize&lt;/code&gt;。目录层由 &lt;code&gt;EntryProcessor&lt;/code&gt;、&lt;code&gt;LogicalRoot&lt;/code&gt;、&lt;code&gt;Directory&lt;/code&gt;、&lt;code&gt;File&lt;/code&gt;、&lt;code&gt;Separated&lt;/code&gt;、&lt;code&gt;SymbolLink&lt;/code&gt; 组成，负责目录树和目录块。数据层由 &lt;code&gt;CompressionLoop&lt;/code&gt;、&lt;code&gt;DecompressionLoop&lt;/code&gt;、&lt;code&gt;DataLoader&lt;/code&gt;、&lt;code&gt;DataExporter&lt;/code&gt;、&lt;code&gt;StrategyFactory&lt;/code&gt;、&lt;code&gt;ICompression&lt;/code&gt;、&lt;code&gt;IEncryption&lt;/code&gt; 组成，覆盖 Huffman、AES 和数据块读写。界面层由 &lt;code&gt;MainWindow&lt;/code&gt;、&lt;code&gt;CompressionWorker&lt;/code&gt;、&lt;code&gt;QThread&lt;/code&gt; 组成，负责输入路径、模式、密码、进度和停止控制。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.sy&lt;/code&gt; 协议对象固定为三段：19 字节文件头、目录块区域、数据块区域。目录块前置 &lt;code&gt;Separated&lt;/code&gt; 标准，数据块按文件拆分，树数据和压缩数据各自带分块信息。路径对象统一经过 &lt;code&gt;EncodingUtils::pathFromUtf8()&lt;/code&gt;、&lt;code&gt;EncodingUtils::pathToUtf8()&lt;/code&gt; 和 &lt;code&gt;path.u8string()&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;职责&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;HeaderWriter&lt;/code&gt; 和 &lt;code&gt;Locator&lt;/code&gt; 负责文件头写入、目录偏移回填、&lt;code&gt;compressedSize&lt;/code&gt; 回填和块边界维护。&lt;code&gt;BinaryStandardLoader&lt;/code&gt; 负责目录块读取、目录块解密和标准项装配，&lt;code&gt;EntryParser&lt;/code&gt; 负责按 &lt;code&gt;FlagType&lt;/code&gt; 解析目录项、文件项、逻辑根目录项和分割项。&lt;code&gt;EntryProcessor&lt;/code&gt; 负责把输入路径转成目录树，再序列化进目录块。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CompressionLoop&lt;/code&gt; 负责压缩主循环，&lt;code&gt;DecompressionLoop&lt;/code&gt; 负责解压主循环，&lt;code&gt;DataLoader&lt;/code&gt; 负责原始数据读取，&lt;code&gt;DataExporter&lt;/code&gt; 负责树数据、压缩数据和分块标准写出。&lt;code&gt;StrategyFactory&lt;/code&gt; 按 &lt;code&gt;CompressionMode&lt;/code&gt; 组装 &lt;code&gt;HuffmanAES&lt;/code&gt;、&lt;code&gt;HuffmanOnly&lt;/code&gt;、&lt;code&gt;AESOnly&lt;/code&gt;、&lt;code&gt;PackOnly&lt;/code&gt;。&lt;code&gt;MainWindow&lt;/code&gt; 和 &lt;code&gt;CompressionWorker&lt;/code&gt; 只负责任务调度、进度回调和线程停止，不处理协议细节。&lt;/p&gt;
&lt;h2&gt;流程&lt;/h2&gt;
&lt;p&gt;归档流程从输入路径列表进入 &lt;code&gt;EntryProcessor&lt;/code&gt;。输入源先挂到 &lt;code&gt;LogicalRoot&lt;/code&gt;，再按 BFS 顺序写成目录项和文件项。目录块按 16KB 分块，每块前写入 &lt;code&gt;Separated&lt;/code&gt; 标准，块内记录 &lt;code&gt;blockSize&lt;/code&gt; 和 AES-CFB 的 IV。目录块写完后，&lt;code&gt;HeaderWriter&lt;/code&gt; 回填 &lt;code&gt;directoryOffset&lt;/code&gt;，文件体写完后，&lt;code&gt;Locator&lt;/code&gt; 回填 &lt;code&gt;compressedSize&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;解压流程从文件头开始。读取 &lt;code&gt;strategy&lt;/code&gt;、&lt;code&gt;version&lt;/code&gt;、&lt;code&gt;directoryOffset&lt;/code&gt; 后，&lt;code&gt;BinaryStandardLoader&lt;/code&gt; 逐块读取目录块，检查 IV，决定是否解密，再把二进制数据交给 &lt;code&gt;EntryParser&lt;/code&gt;。&lt;code&gt;EntryParser&lt;/code&gt; 按 &lt;code&gt;Directory&lt;/code&gt;、&lt;code&gt;File&lt;/code&gt;、&lt;code&gt;LogicalRoot&lt;/code&gt;、&lt;code&gt;Separated&lt;/code&gt;、&lt;code&gt;SymbolLink&lt;/code&gt; 拆成 &lt;code&gt;directoryQueueReady&lt;/code&gt;、&lt;code&gt;entryQueue&lt;/code&gt;、&lt;code&gt;fileQueue&lt;/code&gt;。&lt;code&gt;DecompressionLoop&lt;/code&gt; 先创建目录，再按 &lt;code&gt;fileQueue&lt;/code&gt; 进入数据区读取文件体。&lt;/p&gt;
&lt;p&gt;数据流程按文件拆分。&lt;code&gt;DataLoader&lt;/code&gt; 读取原始数据块，&lt;code&gt;HuffmanCompression&lt;/code&gt; 生成频率表、Huffman 树和编码数据，&lt;code&gt;DataExporter&lt;/code&gt; 写入树块、压缩块和有效位数。启用加密时，输出再进入 &lt;code&gt;AesEncryption&lt;/code&gt;。树数据使用先序遍历序列化，叶子节点写 &lt;code&gt;&apos;l&apos;&lt;/code&gt; 和字节值，内部节点写 &lt;code&gt;&apos;r&apos;&lt;/code&gt;。AES 密钥由 SHA-256 派生，协议层使用 AES-128 CFB，目录块和数据块都按流式长度组织，不引入 PKCS#7 填充。&lt;/p&gt;
&lt;p&gt;路径流程贯穿 GUI、核心层和文件系统。Qt 输入先转成 UTF-8，核心层用 &lt;code&gt;std::string&lt;/code&gt; 表示 UTF-8 文本，进入文件系统前统一走 &lt;code&gt;EncodingUtils::pathFromUtf8()&lt;/code&gt;，返回日志或界面前统一走 &lt;code&gt;EncodingUtils::pathToUtf8()&lt;/code&gt;。目录遍历、文件名序列化、解压输出目录拼接都沿用同一条转换链。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.sy&lt;/code&gt; 文件头、目录块和数据块。格式识别依赖 &lt;code&gt;magicNum_1&lt;/code&gt;、&lt;code&gt;magicNum_2&lt;/code&gt;，模式识别依赖 &lt;code&gt;strategy&lt;/code&gt;，目录读取依赖 &lt;code&gt;directoryOffset&lt;/code&gt;，数据读取依赖 &lt;code&gt;compressedSize&lt;/code&gt; 和 &lt;code&gt;blockSize&lt;/code&gt;。目录块、数据块、IV、偏移量都写进归档内部，不依赖外部清单。&lt;/p&gt;
&lt;p&gt;目录 &lt;code&gt;EntryProcessor&lt;/code&gt;、&lt;code&gt;BinaryStandardLoader&lt;/code&gt;、&lt;code&gt;EntryParser&lt;/code&gt;。输入路径、逻辑根目录、BFS 队列、&lt;code&gt;childCount&lt;/code&gt; 和目录恢复都停在这一层。压缩：&lt;code&gt;CompressionLoop&lt;/code&gt;、&lt;code&gt;DecompressionLoop&lt;/code&gt;、&lt;code&gt;ICompression&lt;/code&gt;、&lt;code&gt;IEncryption&lt;/code&gt;，算法替换不改协议主流程。编码问题用： &lt;code&gt;EncodingUtils&lt;/code&gt;，并且Qt、&lt;code&gt;std::string&lt;/code&gt;、&lt;code&gt;std::filesystem::path&lt;/code&gt; 不应当脱离转换混用。GUI 部分有 &lt;code&gt;MainWindow&lt;/code&gt; 和 &lt;code&gt;CompressionWorker&lt;/code&gt;，界面层不接触目录块、文件头和数据区。&lt;/p&gt;
&lt;h2&gt;限制&lt;/h2&gt;
&lt;p&gt;当前版本以 Windows 为主，路径处理和文件系统行为按 Windows 规则组织。主流程仍是单线程顺序处理，&lt;code&gt;ThreadPool&lt;/code&gt; 和 &lt;code&gt;Scheduler&lt;/code&gt; 还停在接口和实验代码层。压缩算法当前只有 Huffman，AES 还是纯软件实现，长路径分支没有进入发布版本。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;/posts/sfc-dev-log-1/&quot;&gt;开发日志（一）：AES 原型、模块划分与 &lt;code&gt;.sy&lt;/code&gt; 格式雏形&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>My ARPG：场景切换、对话、任务和 UI 管理的 Unity 2D ARPG 原型</title><link>https://www.yonagi.world/posts/unity-arpg-project-intro/</link><guid isPermaLink="true">https://www.yonagi.world/posts/unity-arpg-project-intro/</guid><description>Unity 2D ARPG 原型，包含场景切换、状态恢复、条件对话、任务、商店和 UI 管理。</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;项目仓库：
&lt;a href=&quot;https://gitee.com/KAIDOYONAGI/my_arpg&quot;&gt;Gitee&lt;/a&gt; | &lt;a href=&quot;https://github.com/KAIDO-YONAGI/My_ARPG&quot;&gt;GitHub&lt;/a&gt;
在线试玩：&lt;a href=&quot;https://www.yonagi.world/games/arpg/&quot;&gt;ARPG WebGL Demo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;My ARPG&lt;/code&gt; 基于 Unity &lt;code&gt;2022.3.62f3c1&lt;/code&gt;。原型围绕场景切换、状态恢复、条件对话、任务推进、商店交互和 UI 管理展开。资源加载使用 Addressables，输入使用 Input System，模块通信使用 ScriptableObject 事件。&lt;/p&gt;
&lt;h2&gt;对象&lt;/h2&gt;
&lt;p&gt;工程对象分成场景层、状态层、导航层和交互层。场景层由 &lt;code&gt;InitialLoad&lt;/code&gt;、&lt;code&gt;SceneChanger&lt;/code&gt;、&lt;code&gt;SceneLoadEventSO&lt;/code&gt;、&lt;code&gt;GameSceneSO&lt;/code&gt; 组成，负责持久场景和地图切换。状态层由 &lt;code&gt;DataManager&lt;/code&gt;、&lt;code&gt;ISaveable&lt;/code&gt;、&lt;code&gt;DataDefinition&lt;/code&gt;、&lt;code&gt;Data&lt;/code&gt; 组成，用于对象注册、数据分发和持久化标识。导航层由 &lt;code&gt;AStarPathFinder&lt;/code&gt;、&lt;code&gt;AStarNodeManager&lt;/code&gt;、&lt;code&gt;PathFinderDetails&lt;/code&gt; 组成，底层结构使用 &lt;code&gt;Dictionary&amp;lt;Vector3, PathFinderDetails&amp;gt;&lt;/code&gt; 和 &lt;code&gt;HashSet&amp;lt;Vector3&amp;gt;&lt;/code&gt;。交互层覆盖 &lt;code&gt;NPCStateController&lt;/code&gt;、&lt;code&gt;NPCWander&lt;/code&gt;、&lt;code&gt;NPCPatrol&lt;/code&gt;、&lt;code&gt;NPCChat&lt;/code&gt;、&lt;code&gt;ShopKeeper&lt;/code&gt;、&lt;code&gt;DialogSO&lt;/code&gt;、&lt;code&gt;DialogLine&lt;/code&gt;、&lt;code&gt;DialogOption&lt;/code&gt;、&lt;code&gt;QuestSO&lt;/code&gt;、&lt;code&gt;QuestObjective&lt;/code&gt;、&lt;code&gt;Reward&lt;/code&gt;、&lt;code&gt;QuestProgressData&lt;/code&gt;、&lt;code&gt;ShopManager&lt;/code&gt;、&lt;code&gt;UIManager&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;职责&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;SceneChanger&lt;/code&gt; 负责场景卸载、场景加载、玩家坐标切换和输入恢复，&lt;code&gt;DataManager&lt;/code&gt; 负责 &lt;code&gt;Save()&lt;/code&gt;、&lt;code&gt;Load()&lt;/code&gt; 和 &lt;code&gt;ISaveable&lt;/code&gt; 注册表，&lt;code&gt;AStarPathFinder&lt;/code&gt; 负责 &lt;code&gt;FindPath()&lt;/code&gt;、&lt;code&gt;WorldToCell()&lt;/code&gt;、&lt;code&gt;CellToWorld()&lt;/code&gt;、&lt;code&gt;GetNodeMap()&lt;/code&gt;，&lt;code&gt;AStarNodeManager&lt;/code&gt; 负责导航节点生成。&lt;/p&gt;
&lt;p&gt;交互层的职责按模块拆开。&lt;code&gt;NPCStateController&lt;/code&gt; 维护 &lt;code&gt;Idle&lt;/code&gt;、&lt;code&gt;Wander&lt;/code&gt;、&lt;code&gt;Patrol&lt;/code&gt;、&lt;code&gt;Chat&lt;/code&gt; 状态流，&lt;code&gt;NPCChat&lt;/code&gt; 把交互请求交给 &lt;code&gt;DialogManager&lt;/code&gt;，&lt;code&gt;ShopKeeper&lt;/code&gt; 把商店请求交给 &lt;code&gt;ShopManager&lt;/code&gt;。&lt;code&gt;DialogManager&lt;/code&gt; 负责 &lt;code&gt;MatchConditionsToStartDialog()&lt;/code&gt;、分支选择和 &lt;code&gt;DialogSO.HasChated&lt;/code&gt;，&lt;code&gt;QuestManager&lt;/code&gt; 用 &lt;code&gt;Dictionary&amp;lt;QuestSO, QuestProgressData&amp;gt;&lt;/code&gt; 和 &lt;code&gt;Dictionary&amp;lt;QuestObjective, int&amp;gt;&lt;/code&gt; 维护任务状态，&lt;code&gt;UIManager&lt;/code&gt; 负责 &lt;code&gt;ToggleCanvasEventSO&lt;/code&gt;、&lt;code&gt;ResetCanvas()&lt;/code&gt; 和面板互斥。&lt;/p&gt;
&lt;h2&gt;流程&lt;/h2&gt;
&lt;p&gt;场景流程从 &lt;code&gt;SceneLoadEventSO&lt;/code&gt; 进入 &lt;code&gt;SceneChanger.OnEnable()&lt;/code&gt;，再走 &lt;code&gt;LoadSceneMode.Additive&lt;/code&gt; 和 &lt;code&gt;OnLoadCompleted()&lt;/code&gt;。传送门、菜单、碰撞脚本只发切换请求，坐标写入 &lt;code&gt;newPosition&lt;/code&gt;，缺失时回退到 &lt;code&gt;GameSceneSO.initialPosition&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;存档流程从 &lt;code&gt;VoidEventSO&lt;/code&gt; 进入 &lt;code&gt;DataManager.Save()&lt;/code&gt; 和 &lt;code&gt;DataManager.Load()&lt;/code&gt;。&lt;code&gt;DataManager&lt;/code&gt; 带 &lt;code&gt;[DefaultExecutionOrder(-100)]&lt;/code&gt;，先建立 &lt;code&gt;List&amp;lt;ISaveable&amp;gt;&lt;/code&gt;，再把 &lt;code&gt;Data&lt;/code&gt; 分发给对象。对象侧通过 &lt;code&gt;SaveData(Data data)&lt;/code&gt; 和 &lt;code&gt;LoadData(Data data)&lt;/code&gt; 读写字段，&lt;code&gt;DataDefinition.ID&lt;/code&gt; 用于对象定位，&lt;code&gt;Data.lootsStatsDic&lt;/code&gt; 用于战利品状态恢复。&lt;/p&gt;
&lt;p&gt;寻路流程从 &lt;code&gt;FindPath()&lt;/code&gt; 开始，经过 &lt;code&gt;SearchCheapestCost()&lt;/code&gt;、&lt;code&gt;AddNodeToOpen()&lt;/code&gt;、&lt;code&gt;CanWalkDiagonally()&lt;/code&gt; 完成搜索。&lt;code&gt;optPos&lt;/code&gt; 用于前移起点，&lt;code&gt;NoCoverObstacleNodes()&lt;/code&gt; 用于检查直线路径，对角移动受相邻阻挡检测约束。&lt;/p&gt;
&lt;p&gt;对话流程从 &lt;code&gt;NPCChat&lt;/code&gt; 进入 &lt;code&gt;DialogManager&lt;/code&gt;，再进入 &lt;code&gt;MatchConditionsToStartDialog()&lt;/code&gt;、&lt;code&gt;DialogSO&lt;/code&gt; 和 &lt;code&gt;DialogOption&lt;/code&gt;。角色条件依赖 &lt;code&gt;ConversationHistoryManager&lt;/code&gt; 的 &lt;code&gt;HashSet&amp;lt;CharacterSO&amp;gt;&lt;/code&gt;，物品条件依赖 &lt;code&gt;ItemHistoryManager&lt;/code&gt; 的 &lt;code&gt;Dictionary&amp;lt;ItemSO, int&amp;gt;&lt;/code&gt;，一次性条件依赖 &lt;code&gt;DialogSO.HasChated&lt;/code&gt;。任务流程由 &lt;code&gt;QuestManager.UpdateObjectiveProgress()&lt;/code&gt; 直接读取历史数据，奖励流程由 &lt;code&gt;RaiseRewardEvent()&lt;/code&gt; 写入 &lt;code&gt;InventorySlotsStatsSO&lt;/code&gt;。商店流程从 &lt;code&gt;ShopLoadEventSO&lt;/code&gt; 进入 &lt;code&gt;ShopManager.OnShopLoad()&lt;/code&gt; 和 &lt;code&gt;PopulateShopItems()&lt;/code&gt;，购买与出售都经过 &lt;code&gt;InventoryUpdateRequest.RaiseInventoryUpdateRequest()&lt;/code&gt;。UI 流程由输入检测、&lt;code&gt;ToggleCanvasEventSO&lt;/code&gt; 和 &lt;code&gt;CanvasGroup&lt;/code&gt; 组成，切场景时执行 &lt;code&gt;ResetCanvas()&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;边界&lt;/h2&gt;
&lt;p&gt;场景切换 &lt;code&gt;SceneChanger&lt;/code&gt;，外层对象只保留请求入口。运行时的状态保存： &lt;code&gt;DataManager&lt;/code&gt; 和 &lt;code&gt;ISaveable&lt;/code&gt;，对象侧只处理序列化字段。寻路系统： &lt;code&gt;AStarPathFinder&lt;/code&gt; 和 &lt;code&gt;AStarNodeManager&lt;/code&gt;，NPC、敌人、交互物共享导航数据，不持有网格生成逻辑。&lt;/p&gt;
&lt;p&gt;交互边界按系统拆开。NPC 本体不持有对话 UI、商店 UI、任务 UI。&lt;code&gt;DialogManager&lt;/code&gt; 依赖历史数据，不依赖移动逻辑。&lt;code&gt;QuestManager&lt;/code&gt; 依赖历史系统，不维护对话状态。&lt;code&gt;UIManager&lt;/code&gt; 只处理面板开关，不处理任务、商店、对话数据。&lt;/p&gt;
&lt;h2&gt;限制&lt;/h2&gt;
&lt;p&gt;当前版本覆盖场景切换、对象状态恢复、条件对话、任务统计、商店和面板互斥。完整落盘存档、敌人状态持久化、地图交互对象、背包规则和任务内容仍在补全。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;/posts/unity-arpg-dev-log/&quot;&gt;配套开发日志：My ARPG 开发日志&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>SFC 开发日志（二）：压缩 / 解压、目录恢复与首个 CLI 版本</title><link>https://www.yonagi.world/posts/sfc-dev-log-2/</link><guid isPermaLink="true">https://www.yonagi.world/posts/sfc-dev-log-2/</guid><description>数据块组织、目录恢复、解压流程与首个 CLI 预览版本。</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;项目仓库：
&lt;a href=&quot;https://gitee.com/fifseason/We_compress&quot;&gt;Gitee&lt;/a&gt; | &lt;a href=&quot;https://github.com/KAIDO-YONAGI/Noobs-Compressor&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;依赖部分文件头的实现、目录块和偏移量逻辑实现。开始编写数据区的写入、目录恢复、解压读取和命令行版本，并且构建发布版。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/posts/sfc-dev-log-1/&quot;&gt;上一篇：SFC 开发日志（一）&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;2025 年 12 月 1 日到 2025 年 12 月 2 日：数据块表示&lt;/h2&gt;
&lt;p&gt;压缩模块、加密模块、读取器&lt;code&gt;DataLoader&lt;/code&gt;和导出器&lt;code&gt;DataExporter&lt;/code&gt;统一使用 &lt;code&gt;DataBlock = std::vector&amp;lt;uint8_t&amp;gt;&lt;/code&gt;。压缩模块与文件流解耦。协议层、算法层和导出层通过同一类型传递数据。&lt;/p&gt;
&lt;p&gt;整理&lt;code&gt;Y_flib&lt;/code&gt; 命名空间的初始版。&lt;code&gt;HeaderLoader&lt;/code&gt; 分块读取采用迭代器混合状态机模式处理生产消费耦合。目录、树数据、压缩数据。模块只接收字节数据，不关心上游来自文件、目录项还是算法中间产物。&lt;/p&gt;
&lt;h2&gt;2025 年 12 月 3 日到 2025 年 12 月 6 日：HeaderWriter 扩展与压缩侧联通&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;HeaderWriter v0.1.5&lt;/code&gt; 继续扩展。目录协议增加符号链接标准，格式为链接名长度、目标路径长度、链接名和目标路径。（目前随跨平台方案难产废弃）
目录块和数据块都引入 IV 字段。&lt;code&gt;Separated&lt;/code&gt; 标准的职责从块边界标记扩展为“块大小 + IV + 分块标识”。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| 标志 &apos;4&apos; | 链接名长度(4B) | 目标路径长度(4B) | 链接名 | 目标路径 |
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IV 协议统一放在块分割协议开头。目录块、树数据、压缩数据都通过分割标准记录 IV。读取侧先读标准，再按 IV 决定是否解密（早期按浮点精度随机数生成器随机不到0判断，后期已经改为依照策略头判断整体是不是经过AES加密）。此时写入器负责输出目录结构、回读解压侧所需块信息。&lt;/p&gt;
&lt;p&gt;输出文件流程：写文件头、写目录块、读刚刚写的目录块、按块处理、目录块加密（此时是耦合的）、写进处理后块、回填大小。&lt;code&gt;HeaderWriter&lt;/code&gt;、&lt;code&gt;EntryProcessor&lt;/code&gt;、&lt;code&gt;DataExporter&lt;/code&gt; 与压缩模块围绕同一个输出文件（协议化目录）工作。&lt;/p&gt;
&lt;h2&gt;2025 年 12 月 8 日到 2025 年 12 月 9 日：AES 模块补齐&lt;/h2&gt;
&lt;p&gt;AES 从独立算法代码转成归档流程模块。密钥派生仍然使用 SHA-256 的前 16 字节，密钥扩展生成 44 个轮密钥字，主体保持标准 10 轮 AES-128。添加乘法表 &lt;code&gt;GF_MUL_2&lt;/code&gt;、&lt;code&gt;GF_MUL_3&lt;/code&gt;、&lt;code&gt;GF_MUL_9&lt;/code&gt;、&lt;code&gt;GF_MUL_11&lt;/code&gt;、&lt;code&gt;GF_MUL_13&lt;/code&gt;、&lt;code&gt;GF_MUL_14&lt;/code&gt; ，利用缓存命中减少运行时 GF(2^8) 乘法计算耗时，实测目前软件AES方案增快80%以上。&lt;/p&gt;
&lt;h2&gt;2025 年 12 月 10 日到 2025 年 12 月 12 日：BFS 目录遍历与逻辑根目录&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;EntryProcessor&lt;/code&gt; BFS 目录遍历方案。输入文件和输入目录先挂到逻辑根目录下，再由队列按层序遍历。目录项进入 &lt;code&gt;entryQueue&lt;/code&gt;，子目录继续入队，文件项写入文件标准。目录块每写满 16KB，就插入一条分割标准，把当前块大小和 IV 写入协议。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void EntryProcessor::flowScanner(...)
{
    // 1. 写入逻辑根节点
    // 2. 处理用户指定的文件/目录列表
    // 3. 循环从队列取出目录，处理其内容
    // 4. 遇到子目录时加入队列继续遍历
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;BFS 目录遍历直接服务目录恢复。解压器不需要外部目录描述文件，只按目录标准和 &lt;code&gt;childCount&lt;/code&gt; 推进队列，就能还原父目录、子目录和同层兄弟项的关系。协议为处理多个文件、文件夹逻辑根目录（本质森林合成一颗树）。利用逻辑根目录提供一个根节点（无序）。&lt;/p&gt;
&lt;h2&gt;2025 年 12 月 13 日到 2025 年 12 月 17 日：解压流程&lt;/h2&gt;
&lt;p&gt;解压流程主体是 &lt;code&gt;BinaryStandardLoader&lt;/code&gt;。类内部维护 &lt;code&gt;fileQueue&lt;/code&gt;、&lt;code&gt;entryQueue&lt;/code&gt;、&lt;code&gt;directoryQueueReady&lt;/code&gt;、&lt;code&gt;blockPosition&lt;/code&gt;，分别负责待解压文件项、目录项上下文、目录恢复顺序和目录块回写位置。读取器先打开归档文件，验证魔数，读取文件头，定位到 &lt;code&gt;directoryOffset&lt;/code&gt;，逐块读取目录块，再把数据交给 &lt;code&gt;EntryParser&lt;/code&gt;解析。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;读取 .sy 文件
    -&amp;gt; 验证魔数
    -&amp;gt; 跳转到目录块偏移
    -&amp;gt; 按需解密目录块
    -&amp;gt; 解析文件队列和目录队列
    -&amp;gt; 创建目录结构
    -&amp;gt; 逐块读取数据区
        -&amp;gt; 解密 Huffman 树
        -&amp;gt; 重建 Huffman 树
        -&amp;gt; 解密压缩数据
        -&amp;gt; Huffman 解码
        -&amp;gt; 写回原文件
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;EntryParser&lt;/code&gt; 解析目录标准和文件标准后，把文件条目压入 &lt;code&gt;fileQueue&lt;/code&gt;，把目录路径压入 &lt;code&gt;directoryQueueReady&lt;/code&gt;。&lt;code&gt;DecompressionLoop&lt;/code&gt; 先创建目录，再根据文件条目进入数据区。文件条目中的第二字段在压缩场景承担偏移量语义，在解压场景承担 &lt;code&gt;compressedSize&lt;/code&gt; 语义。&lt;/p&gt;
&lt;h2&gt;2025 年 12 月 18 日到 2025 年 12 月 25 日：工程整理与 CLI 交互&lt;/h2&gt;
&lt;p&gt;工程整理与主流程开发。huffman的&lt;code&gt;std::map&lt;/code&gt; 替换为 &lt;code&gt;std::unordered_map&lt;/code&gt;，整理优化CLI相关代码（GUI版本已删除的main.cpp）。&lt;/p&gt;
&lt;p&gt;采用了耦合设计：目录块、树数据、压缩数据、加密过程全部写进压缩 / 解压主循环。&lt;/p&gt;
&lt;h2&gt;2025 年 12 月 30 日到 2025 年 12 月 31 日：Huffman 单字符边界问题&lt;/h2&gt;
&lt;p&gt;单字符输入的协议边界：数据块全部由同一个字节组成时，Huffman 树只有一个叶子节点，常规的构造方式失效。树生成失败后，编码和回读都会随之失效。&lt;/p&gt;
&lt;p&gt;处理方式是给单字符场景固定一位编码。树节点数量为 1 时，编码直接写成 &lt;code&gt;{0}&lt;/code&gt;，长度记为 1。压缩侧仍能生成树数据和编码数据，解压侧也按同一规则恢复。单字符文件和单字符数据块纳入标准压缩 / 解压流程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (countLeaves(treeroot) == 1) {
    hashtab[onlyChar].code = {0};
    hashtab[onlyChar].codelen = 1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2026 年 1 月 1 日到 2026 年 1 月 6 日：首个 CLI 预览版本&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;v1.0.0 Preview&lt;/code&gt; 首个release。实现了CLI版本的加密压缩与解压全流程。修复数据区解码和单字符边界问题。&lt;/p&gt;
&lt;p&gt;预览版仍有稳定性修正项：目录偏移量类型统一为 &lt;code&gt;uint64_t&lt;/code&gt;，目录缓冲区大小固定为 &lt;code&gt;16KB&lt;/code&gt;，部分 &lt;code&gt;constexpr const&lt;/code&gt; 历史写法被清理，项目说明与 README 同步补全。归档体积超过 4GB 时，32 位偏移量没有可用空间，因此偏移量类型固定为 &lt;code&gt;uint64_t&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;结果&lt;/h2&gt;
&lt;p&gt;主逻辑完成，引入目录遍历与逻辑根目录，&lt;code&gt;BinaryStandardLoader&lt;/code&gt; 和 &lt;code&gt;EntryParser&lt;/code&gt; 把目录恢复纳入主流程，Huffman 单字符边界bug修复，发布CLI 形式的压缩与解压工具。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;/posts/sfc-dev-log-3/&quot;&gt;下一篇：SFC 开发日志（三）：CLI 稳定化、Qt GUI 与发布&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>SFC 开发日志（三）：CLI 稳定化、Qt GUI 与发布</title><link>https://www.yonagi.world/posts/sfc-dev-log-3/</link><guid isPermaLink="true">https://www.yonagi.world/posts/sfc-dev-log-3/</guid><description>CLI 稳定化、Qt GUI、编码处理、多策略支持与单文件发布。</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;项目仓库：
&lt;a href=&quot;https://gitee.com/fifseason/We_compress&quot;&gt;Gitee&lt;/a&gt; | &lt;a href=&quot;https://github.com/KAIDO-YONAGI/Noobs-Compressor&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;处理目录块边界、GUI 、UTF-8 路径、策略模式、单文件发布等问题。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/posts/sfc-dev-log-2/&quot;&gt;上一篇：SFC 开发日志（二）&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;2026 年 3 月 2 日到 2026 年 3 月 15 日：CLI 稳定化&lt;/h2&gt;
&lt;p&gt;CLI debug、refactor。&lt;code&gt;FlagType&lt;/code&gt; 改成强类型枚举，目录接口、工具类接口、文件已存在时的处理方式、目录队列逻辑同步整理。目录标准、文件标准、分割标准共享同一组枚举和偏移量规则，目录恢复与数据区读取都按统一类型解释。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;enum class FlagType : char
{
    Directory = &apos;0&apos;,
    File = &apos;1&apos;,
    Separated = &apos;2&apos;,
    LogicalRoot = &apos;3&apos;,
    SymbolLink = &apos;4&apos;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;目录块边界写入问题。目录条目恰好落在分块边界时，流程没有正常进行，产生空分块或目录解析错位，具体问题在于请求的流程逻辑的遗漏。&lt;/p&gt;
&lt;p&gt;关于长路径问题。尝试在&lt;code&gt;PathTransfer::transPath()&lt;/code&gt; 给绝对路径加上 &lt;code&gt;\\?\&lt;/code&gt; 前缀，用于解决 Windows 路径长度限制。由于操作系统实际上还是禁止了长路径的出现，项目只能使用 Windows 路径处理和 UTF-8 中文路径。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 1 日：构建系统调整&lt;/h2&gt;
&lt;p&gt;构建系统改为 MSVC + CMake。关闭&lt;code&gt;CMAKE_INTERPROCEDURAL_OPTIMIZATION&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;仅仅是为了使用VS的性能分析报告&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 12 日到 2026 年 4 月 15 日：文档整理与 GUI 工程建立&lt;/h2&gt;
&lt;p&gt;代码清理与 GUI 开发。开始编写 Qt Widgets 。编写CMake 配置和后台任务执行框架。&lt;/p&gt;
&lt;p&gt;GUI 的设计隔离： &lt;code&gt;Y_Manager&lt;/code&gt; 和 &lt;code&gt;CompressorFileSystem&lt;/code&gt;负责主逻辑。GUI 负责参数录入、结果展示和线程调度。&lt;/p&gt;
&lt;p&gt;修复&lt;code&gt;directoryOffset&lt;/code&gt; 的写入时机问题。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 16 日：Qt GUI 主体&lt;/h2&gt;
&lt;p&gt;GUI 主体围绕 &lt;code&gt;MainWindow&lt;/code&gt;、&lt;code&gt;CompressionWorker&lt;/code&gt;、&lt;code&gt;QThread&lt;/code&gt; 组织。&lt;code&gt;MainWindow&lt;/code&gt; 收集源路径、输出目录、模式和密码。&lt;code&gt;CompressionWorker&lt;/code&gt; 在后台线程调用 &lt;code&gt;MainLoop&lt;/code&gt;、&lt;code&gt;CompressionLoop&lt;/code&gt;、&lt;code&gt;DecompressionLoop&lt;/code&gt;。进度通过信号送回 UI 线程。界面层不直接访问目录块、数据区和压缩模块。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MainWindow (UI线程)
    -&amp;gt; QThread
        -&amp;gt; CompressionWorker
            -&amp;gt; CompressionLoop / DecompressionLoop
    &amp;lt;- detailedProgress / finished
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GUI 接入后，进度信号频率需要限流。后台线程若每处理一小段数据就发出信号，UI 线程会堆积刷新请求。处理方式分成两层：&lt;code&gt;MainLoop&lt;/code&gt; 控制核心层回调频率，&lt;code&gt;CompressionWorker&lt;/code&gt; 按时间和百分比变化量再做一层节流。双层节流下，进度显示保持连续。&lt;/p&gt;
&lt;p&gt;窗口关闭期间的线程退出。后台线程执行中直接关闭窗口，文件句柄、缓冲区和输出状态容易残留。GUI 因此加入 &lt;code&gt;std::atomic&amp;lt;bool&amp;gt; m_stopRequested&lt;/code&gt;。主线程发出停止请求，后台线程在进度回调和循环中检查标记，析构阶段等待线程退出。停止逻辑只处理线程与资源，不改协议结构。&lt;/p&gt;
&lt;p&gt;文件句柄和缓冲区释放。&lt;code&gt;BinaryStandardLoader::setAllLoopDone()&lt;/code&gt;、&lt;code&gt;DecompressionLoop::createFile()&lt;/code&gt;、&lt;code&gt;std::vector&lt;/code&gt; 缓冲复用、&lt;code&gt;Heffman::merge_ttabs()&lt;/code&gt; 的容量释放都进入正式代码。长任务运行期间，已经处理完的缓冲区会及时释放。解压阶段输出文件句柄也会在写入结束后关闭。&lt;/p&gt;
&lt;h2&gt;中文路径与编码处理&lt;/h2&gt;
&lt;p&gt;GUI 接入后的路径编码差异。Qt 层传入 UTF-8 字符串，&lt;code&gt;std::filesystem&lt;/code&gt; 在 Windows 下返回的路径文本可能关联本地代码页。路径拼接、文件名恢复和日志显示都依赖统一转换规则，中文输出目录尤其敏感。&lt;/p&gt;
&lt;p&gt;修正规则集中在 &lt;code&gt;EncodingUtils&lt;/code&gt;。Qt 边界处统一使用 UTF-8 作为文本协议，&lt;code&gt;QString&lt;/code&gt; 进入核心层前先转 UTF-8，进入文件系统前再用 &lt;code&gt;pathFromUtf8()&lt;/code&gt;，从 &lt;code&gt;std::filesystem::path&lt;/code&gt; 回到日志或 GUI 时再用 &lt;code&gt;pathToUtf8()&lt;/code&gt;。目录遍历和文件名序列化统一使用 &lt;code&gt;entry.path().filename().u8string()&lt;/code&gt;。&lt;code&gt;toStdString()&lt;/code&gt;。关于输出目录乱码：UTF-8 文本先转路径对象，再交给 &lt;code&gt;DecompressionLoop&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;统一规则覆盖中文路径、中文输出目录、日志显示和 GUI 展示。 &lt;code&gt;EncodingUtils&lt;/code&gt; ，&lt;code&gt;QString&lt;/code&gt;、&lt;code&gt;std::string&lt;/code&gt;、&lt;code&gt;std::filesystem::path&lt;/code&gt; 统一处理三个文本体系的路径逻辑。&lt;/p&gt;
&lt;h2&gt;Qt 工具链与系统兼容性&lt;/h2&gt;
&lt;p&gt;GUI 发布的依赖为 Qt 6.2.4 LTS。MSYS2 MinGW 15.x 构建版本在运行时出现过 &lt;code&gt;nanosleep64&lt;/code&gt; 缺失，Qt 6.10.1 的部分 API 在旧版 Windows 10 环境下也不稳定。Qt 6.2.4 LTS 用于统一图形界面、路径转换、线程模型和静态发布环境。&lt;/p&gt;
&lt;p&gt;GUI 兼容 Windows 10 1809 及以上版本。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 17 日：多策略支持与发布形态调整&lt;/h2&gt;
&lt;p&gt;主流程原本把 &lt;code&gt;Huffman + AES&lt;/code&gt; 写死在内部。重构后，&lt;code&gt;CompressionMode&lt;/code&gt; 枚举、&lt;code&gt;StrategyFactory&lt;/code&gt;、&lt;code&gt;ICompression&lt;/code&gt;、&lt;code&gt;IEncryption&lt;/code&gt;、&lt;code&gt;NullCompression&lt;/code&gt;、&lt;code&gt;NullEncryption&lt;/code&gt; 一并接入，压缩和加密组合改由运行时装配。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;enum class CompressionMode : uint8_t
{
    HuffmanAES  = 0,
    HuffmanOnly = 1,
    AESOnly     = 2,
    PackOnly    = 3
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;CompressionLoop&lt;/code&gt;、&lt;code&gt;DecompressionLoop&lt;/code&gt; 和 &lt;code&gt;BinaryStandardLoader&lt;/code&gt; 由依赖具体类改为依赖接口。&lt;code&gt;HeaderWriter&lt;/code&gt; 负责把策略号写入文件头，解压侧通过 &lt;code&gt;Header.strategy&lt;/code&gt; 还原模式。策略号 &lt;code&gt;0&lt;/code&gt; 继续映射 &lt;code&gt;HuffmanAES&lt;/code&gt;，旧归档文件保持兼容。&lt;/p&gt;
&lt;p&gt;发布形态同步调整。动态部署包体约 57MB，Qt DLL、渲染依赖和资源文件分散在目录中。静态发布改用 Qt 6.2.4 静态库，构建开关通过 &lt;code&gt;USE_STATIC_QT&lt;/code&gt; 控制，翻译文件和图片资源内嵌进可执行文件，背景图从 PNG 改成 JPEG。默认发布体积约 16MB，发布目录不携带额外依赖。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 18 日到 2026 年 4 月 19 日：编码整理、翻译与工程清理&lt;/h2&gt;
&lt;p&gt;编码规则固定为：GUI 输入统一转 UTF-8，核心层字符串按 UTF-8 组织，真正接触文件系统时再转成 &lt;code&gt;std::filesystem::path&lt;/code&gt;。规则覆盖 GUI 压缩输入、解压输出目录、目录遍历结果和日志文本。编码转换职责全部归入 &lt;code&gt;EncodingUtils&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;GUI 多语言规则固定为：界面文案统一使用 &lt;code&gt;tr()&lt;/code&gt; 包装，翻译资源通过 &lt;code&gt;resources.qrc&lt;/code&gt; 内嵌，语言选择优先读取 &lt;code&gt;SFC_GUI_LANGUAGE&lt;/code&gt;，没有显式指定时再读取 &lt;code&gt;QLocale::system()&lt;/code&gt;。单 &lt;code&gt;exe&lt;/code&gt; 发布下，翻译资源不依赖外部目录。日志和技术状态文本保持英文，控件文本按语言环境切换。&lt;/p&gt;
&lt;p&gt;工程整理还包括头文件、命名空间、本地构建目录 &lt;code&gt;.gitignore&lt;/code&gt; 和临时验证目录清理。目录块规则、编码规则、GUI 工具链和策略模式稳定后，代码布局与功能布局对齐。&lt;/p&gt;
&lt;h2&gt;结果&lt;/h2&gt;
&lt;p&gt;从CLI 到桌面程序（GUI）。处理的问题：目录块写入顺序、目录恢复队列、输出目录编码、目录偏移量回填和目录块加密、GUI、多策略和单文件发布。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;/posts/sfc-project-intro/&quot;&gt;返回项目介绍：SFC&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>SFC 开发日志（一）：AES 原型、模块划分与 .sy 格式雏形</title><link>https://www.yonagi.world/posts/sfc-dev-log-1/</link><guid isPermaLink="true">https://www.yonagi.world/posts/sfc-dev-log-1/</guid><description>AES 原型、模块边界、Header 设计和归档格式雏形。</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;项目仓库：
&lt;a href=&quot;https://gitee.com/fifseason/We_compress&quot;&gt;Gitee&lt;/a&gt; | &lt;a href=&quot;https://github.com/KAIDO-YONAGI/Noobs-Compressor&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;开发 AES-128 原型、目录读取、文件头写入、偏移量定位和 Huffman 树序列化。
.sy协议：文件系统信息写进二进制文件，读取器按同一规则读回。涉及的主要模块有：文件头、目录块、数据区、定位工具和读取器。&lt;/p&gt;
&lt;h2&gt;2025 年 9 月 29 日到 2025 年 10 月 5 日：AES 原型与密钥入口&lt;/h2&gt;
&lt;p&gt;开发 &lt;code&gt;Aes.cpp&lt;/code&gt; 和 &lt;code&gt;Aes.h&lt;/code&gt;。首先实现主逻辑，接着补齐密钥对齐。密码入口采用 SHA-256 派生，再截取前 16 字节作为 AES-128 密钥。AES 模块内部只处理 128 位密钥。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void SubBytes(state_t &amp;amp;state);
void ShiftRows(state_t &amp;amp;state);
void MixColumns(state_t &amp;amp;state);
void AddRoundKey(state_t &amp;amp;state);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;AES 初版使用 ECB。由于系统尚未引入目录块、数据块、偏移量、IV 和文件头，目前仅做实验性实现&lt;/p&gt;
&lt;h2&gt;2025 年 10 月 11 日到 2025 年 10 月 18 日：结构设计与并发架构的设计（虽然最后并未使用）&lt;/h2&gt;
&lt;p&gt;代码从单文件算法实验转向模块化结构。目录内出现 &lt;code&gt;Scheduler&lt;/code&gt;、&lt;code&gt;ThreadPool&lt;/code&gt;、&lt;code&gt;TaskQueue&lt;/code&gt;、&lt;code&gt;DataInteraction&lt;/code&gt; 等名称，职责划分也随之明确：调度层负责组织流程，压缩与加密模块只处理字节流，数据交互层负责把文件系统内容转成模块输入。&lt;/p&gt;
&lt;p&gt;线程池和任务队列先以接口形式落位。主流程没有并入并发执行，但 &lt;code&gt;TaskMonitor&lt;/code&gt;、条件变量、队列和销毁逻辑已经编写完成。主流程保持单线程时使用同一份数据交换结构，并发分支接入时也不需要重写。&lt;/p&gt;
&lt;p&gt;模块化设计把压缩与加密拆开。目录树读取器、文件头写入器、数据块读取器被划入协议层。协议层与算法层分离后，Huffman、AES、GUI 共享同一份文件系统结构。&lt;/p&gt;
&lt;h2&gt;2025 年 10 月 21 日到 2025 年 10 月 30 日：工具类与偏移量&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;CompressionModules/heffman&lt;/code&gt; 负责 Huffman，&lt;code&gt;EncryptionModules/aes&lt;/code&gt; 负责 AES，&lt;code&gt;CompressorFileSystem/DataCommunication&lt;/code&gt; 负责目录树、文件头、偏移量、路径和数据块读写。&lt;/p&gt;
&lt;p&gt;需要注意的是，并发代码承担的是模块交接任务。&lt;code&gt;TaskMonitor&lt;/code&gt; 使用 &lt;code&gt;vector&lt;/code&gt;、&lt;code&gt;condition_variable&lt;/code&gt; 和 &lt;code&gt;mutex&lt;/code&gt; 管理多条队列。工程结构已经脱离单文件测试程序的写法。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Locator&lt;/code&gt; ，关键工具。用于归档文件写入文件头后偏移量字段回填。负责在文件头、目录块、数据区之间定位，封装并且统一所有 &lt;code&gt;seekg&lt;/code&gt; 和 &lt;code&gt;seekp&lt;/code&gt;的调用。&lt;code&gt;directoryOffset&lt;/code&gt;、&lt;code&gt;compressedSize&lt;/code&gt;、目录块大小和文件头定位从此纳入同一套偏移量规则。&lt;/p&gt;
&lt;p&gt;协议中出现需要回填的字段，不同区域通过偏移量互相引用。&lt;/p&gt;
&lt;h2&gt;2025 年 11 月 1 日到 2025 年 11 月 13 日：HeaderReader、filesystem 与目录信息读取&lt;/h2&gt;
&lt;p&gt;读取器 &lt;code&gt;Reader&lt;/code&gt;、&lt;code&gt;ReaderUpdate&lt;/code&gt;、&lt;code&gt;Reader_filesystem&lt;/code&gt;、&lt;code&gt;HeaderReader&lt;/code&gt; 的重构。主要处理文件系统路径接入、目录项结构化读取、位流与普通文件流统一、Windows 路径编码处理。读取器形态由普通文件流读取转向“按目录项解释字节流”。&lt;/p&gt;
&lt;p&gt;抛弃posix（我不会），使用标准库的&lt;code&gt;filesystem&lt;/code&gt;。&lt;code&gt;MyQueue&lt;/code&gt;、辅助结构、目录队列、文件队列成形，构建目录块解析方案。&lt;/p&gt;
&lt;p&gt;Windows 路径问题。宽字符路径做过试验，最终规则尚未固定，但编码已经进入协议设计范围。&lt;/p&gt;
&lt;p&gt;读取器重构后，目录信息进入内存结构，由读取器和队列维护。&lt;/p&gt;
&lt;h2&gt;2025 年 11 月 17 日到 2025 年 11 月 30 日：HeaderWriter、Huffman 序列化与 Header 雏形&lt;/h2&gt;
&lt;p&gt;开始写入端的编写。&lt;code&gt;HeaderLoader&lt;/code&gt;、&lt;code&gt;FileLibrary&lt;/code&gt;、&lt;code&gt;DirectoryReader&lt;/code&gt;、&lt;code&gt;HeaderWriter&lt;/code&gt; 。读取和写入形成对应关系：目录信息如何落盘，解压侧就按同样规则读回。文件头预留哪些字段，数据区写入时就按同样位置回填。&lt;/p&gt;
&lt;p&gt;Huffman 编码树保存方式固定。树序列化采用先序遍历，叶子节点写 &lt;code&gt;&apos;l&apos;&lt;/code&gt; 和字节值，内部节点写 &lt;code&gt;&apos;r&apos;&lt;/code&gt;。解压侧根据树数据重建 Huffman 树，不重新扫描整文件统计频率。树的序列化方式固定后，压缩侧与解压侧共享同一份树结构，数据块也具备独立编码和独立恢复条件。&lt;/p&gt;
&lt;p&gt;文件头&lt;code&gt;Header&lt;/code&gt;结构同步定形。包含 魔数、策略号、版本号、保留位、目录偏移量、尾部魔数。&lt;/p&gt;
&lt;p&gt;文件头里预留八位&lt;code&gt;strategy&lt;/code&gt;。为多策略模式保留扩展位。&lt;/p&gt;
&lt;h2&gt;2025 年 11 月 29 日到 2025 年 11 月 30 日：AES 从 ECB 转向 CFB&lt;/h2&gt;
&lt;p&gt;目录块和数据块纳入协议后，AES 模式需要随协议组织方式调整。归档文件按给定大小数据块写入，不做16B块对齐。目录信息和数据信息都依赖块分割协议。AES加密模式从CBC改成 CFB。原因是CFB 不改变数据长度，更加能准确还原信息，也便于在分割标准中记录 IV。&lt;/p&gt;
&lt;h2&gt;结果&lt;/h2&gt;
&lt;p&gt;AES 原型脱离单文件实验。目录结构、读取器、写入器、定位工具和偏移量规则纳入同一套代码。Huffman 树序列化方式固定，文件头字段和协议边界确定。CLI、目录恢复、数据区写入、GUI 都建立在这组协议代码上。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;/posts/sfc-dev-log-2/&quot;&gt;下一篇：SFC 开发日志（二）：压缩 / 解压、目录恢复与首个 CLI 版本&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>My ARPG 开发日志：场景切换、A*、对话与任务系统</title><link>https://www.yonagi.world/posts/unity-arpg-dev-log/</link><guid isPermaLink="true">https://www.yonagi.world/posts/unity-arpg-dev-log/</guid><description>场景切换、A*、对话、任务、商店和 UI 管理。</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;项目仓库：
&lt;a href=&quot;https://gitee.com/KAIDOYONAGI/my_arpg&quot;&gt;Gitee&lt;/a&gt; | &lt;a href=&quot;https://github.com/KAIDO-YONAGI/My_ARPG&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;开发记录覆盖场景切换、状态恢复、A*、NPC 状态、条件对话、任务、商店和 UI 路由。代码组织围绕事件、ScriptableObject 数据和多场景结构展开。每个模块单独建类，数据依赖和调用顺序落在同一条主链上。&lt;/p&gt;
&lt;h2&gt;2026 年 3 月 18 日到 2026 年 3 月 20 日：项目初始化与基础结构&lt;/h2&gt;
&lt;p&gt;工程已有玩家状态机、击退处理、商店入口和部分目录结构。初始化部分先整理脚本目录、命名和公共依赖。单位脚本、对话脚本、场景脚本、UI 脚本、ScriptableObject 资源分别归档。预制件、动画和 SO 资源同步分组。任务、对话、商店和多场景切换共享统一目录结构与 Inspector 绑定规则。&lt;/p&gt;
&lt;p&gt;目录结构固定后，脚本职责随目录边界拆开。单位逻辑与 UI 逻辑不放在同一目录，对话系统与场景系统各自持有独立入口。多系统协作依赖稳定命名、稳定资源路径和稳定事件引用。&lt;/p&gt;
&lt;h2&gt;2026 年 3 月 21 日到 2026 年 3 月 24 日：场景切换与状态保存打底&lt;/h2&gt;
&lt;p&gt;场景切换和状态恢复由 &lt;code&gt;InitialLoad&lt;/code&gt;、&lt;code&gt;SceneChanger&lt;/code&gt;、&lt;code&gt;DataManager&lt;/code&gt;、&lt;code&gt;ISaveable&lt;/code&gt; 四层承担。入口场景通过 &lt;code&gt;Addressables.LoadSceneAsync(persistentScene)&lt;/code&gt; 加载持久场景，后续加载事件由 &lt;code&gt;SceneLoadEventSO&lt;/code&gt; 广播给 &lt;code&gt;SceneChanger&lt;/code&gt;。&lt;code&gt;SceneChanger&lt;/code&gt; 收到请求后禁用 &lt;code&gt;PlayerMovement&lt;/code&gt;、重置血量、暂停时间、记录目标场景和目标位置，再按淡入标记控制过渡动画。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SceneChanger&lt;/code&gt; 的核心流程是：卸载当前场景，以 &lt;code&gt;LoadSceneMode.Additive&lt;/code&gt; 异步加载目标场景，设置玩家坐标，在 &lt;code&gt;OnLoadCompleted()&lt;/code&gt; 中恢复输入和时间。输入禁用、血量重置、暂停和位置切换都集中在同一个类内，传送门、菜单和碰撞脚本只负责发起请求。&lt;/p&gt;
&lt;p&gt;状态恢复层由 &lt;code&gt;DataManager&lt;/code&gt; 和 &lt;code&gt;ISaveable&lt;/code&gt; 组成。&lt;code&gt;DataManager&lt;/code&gt; 带有 &lt;code&gt;[DefaultExecutionOrder(-100)]&lt;/code&gt;，初始化顺序早于普通脚本，内部维护 &lt;code&gt;List&amp;lt;ISaveable&amp;gt;&lt;/code&gt;。保存事件触发时，&lt;code&gt;Save()&lt;/code&gt; 遍历注册对象，把 &lt;code&gt;Data&lt;/code&gt; 实例交给各对象写入。读取事件触发时，&lt;code&gt;Load()&lt;/code&gt; 再把同一份 &lt;code&gt;Data&lt;/code&gt; 发回各对象。对象侧实现 &lt;code&gt;GetDataID()&lt;/code&gt;、&lt;code&gt;SaveData()&lt;/code&gt;、&lt;code&gt;LoadData()&lt;/code&gt; 即可。&lt;/p&gt;
&lt;p&gt;战利品状态接入保存流程。&lt;code&gt;Data.lootsStatsDic&lt;/code&gt; 记录战利品位置和拾取状态，用于重载场景时恢复交互物状态。GUID 与对象状态进入同一张数据表。&lt;/p&gt;
&lt;h2&gt;2026 年 3 月 25 日到 2026 年 3 月 31 日：A* 寻路&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;AStarPathFinder&lt;/code&gt; 完成主要结构。路径搜索接口是 &lt;code&gt;FindPath(Vector3 optPos, Vector3 startPos, Vector3 endPos)&lt;/code&gt;，内部先把世界坐标转成网格坐标，再用 &lt;code&gt;Dictionary&amp;lt;Vector3, PathFinderDetails&amp;gt;&lt;/code&gt; 维护开启列表，用 &lt;code&gt;HashSet&amp;lt;Vector3&amp;gt;&lt;/code&gt; 维护关闭列表。&lt;code&gt;SearchCheapestCost()&lt;/code&gt; 负责取总代价最低节点，&lt;code&gt;RetracePath()&lt;/code&gt; 负责从终点回溯父节点并生成路径栈。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;optPos&lt;/code&gt; 是一层前置优化。&lt;code&gt;optPos&lt;/code&gt; 不为零时，程序先检查该点对应网格是否可通过，再用 &lt;code&gt;NoCoverObstacleNodes()&lt;/code&gt; 判断起点到 &lt;code&gt;optPos&lt;/code&gt; 的直线段是否存在障碍。直线路径可用时，搜索起点前移到 &lt;code&gt;optPos&lt;/code&gt;，开启列表规模随之缩小。&lt;/p&gt;
&lt;p&gt;八方向移动与对角穿墙检测是寻路层的另一条规则。&lt;code&gt;AddNodeToOpen()&lt;/code&gt; 在展开邻居时调用 &lt;code&gt;CanWalkDiagonally()&lt;/code&gt;。斜向移动时，如果横向和纵向相邻格子都被障碍占用，路径搜索禁止沿对角线穿过。路径结果因此与碰撞结果保持一致。&lt;/p&gt;
&lt;p&gt;导航数据由 &lt;code&gt;AStarNodeManager&lt;/code&gt; 从 Tilemap 和 &lt;code&gt;Collider2D&lt;/code&gt; 生成。地图切换后，沿用相同图层与碰撞规则即可刷新网格数据。NPC、敌人和交互对象共享这层导航数据。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 1 日到 2026 年 4 月 6 日：NPC、动画与对话入口&lt;/h2&gt;
&lt;p&gt;NPC 行为按状态拆开。&lt;code&gt;NPCStateController&lt;/code&gt; 管理 &lt;code&gt;Idle&lt;/code&gt;、&lt;code&gt;Wander&lt;/code&gt;、&lt;code&gt;Patrol&lt;/code&gt;、&lt;code&gt;Chat&lt;/code&gt;，&lt;code&gt;NPCWander&lt;/code&gt; 与 &lt;code&gt;NPCPatrol&lt;/code&gt; 处理移动，&lt;code&gt;NPCChat&lt;/code&gt; 处理交互入口和对话触发。状态切换通过启用或禁用脚本完成。角色接近 NPC 并触发交互时，移动脚本停下，对话入口接管当前状态。&lt;/p&gt;
&lt;p&gt;动画与交互时机跟随同一条状态链移动。&lt;code&gt;NPCChat&lt;/code&gt; 负责拉起 &lt;code&gt;DialogManager&lt;/code&gt;，&lt;code&gt;NPCStateController&lt;/code&gt; 负责停掉游荡或巡逻脚本。移动、动画、交互、面板打开分别由不同脚本承担。&lt;/p&gt;
&lt;p&gt;店主和普通 NPC 沿用同样的拆分方式。店主脚本只负责商店入口，商品内容和商店 UI 交给 &lt;code&gt;ShopManager&lt;/code&gt;。普通 NPC 只负责对话入口，对话条件与历史回写交给 &lt;code&gt;DialogManager&lt;/code&gt; 和历史管理器。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 7 日到 2026 年 4 月 10 日：菜单、暂停与 Retry 逻辑&lt;/h2&gt;
&lt;p&gt;ESC 菜单、暂停和 Retry 共用输入、动画、场景和玩家状态。时序问题集中在暂停状态、死亡重载、淡入淡出和输入恢复几个位置。由UI 管理层统一控制，不让单个按钮各自维护一套条件。&lt;/p&gt;
&lt;p&gt;UI 射线阻挡、面板状态残留、按钮事件和场景状态不同步。问题在 UI 管理层。商店、任务、对话、属性和 ESC 面板共用一套开关路由，状态切换由统一管理器分发。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 13 日到 2026 年 4 月 19 日：条件对话与对话历史&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;DialogSO&lt;/code&gt;、&lt;code&gt;DialogManager&lt;/code&gt;、&lt;code&gt;ConversationHistoryManager&lt;/code&gt;、&lt;code&gt;ItemHistoryManager&lt;/code&gt; 组成一套结构。&lt;code&gt;DialogSO&lt;/code&gt; 保存主说话角色、对话文本数组、选项分支、角色前置条件、物品前置条件、拒绝对话节点和一次性触发限制。对话节点从“文本 + 下一句”扩展成带条件、带分支、带历史回写的数据对象。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;DialogManager.StartDialog()&lt;/code&gt; 先执行 &lt;code&gt;MatchConditionsToStartDialog()&lt;/code&gt;。角色条件通过 &lt;code&gt;ConversationHistoryManager.CharactersHasChated&lt;/code&gt; 检查，物品条件通过 &lt;code&gt;ItemHistoryManager.HasPickedOverAmount()&lt;/code&gt; 检查，一次性对话通过 &lt;code&gt;DialogSO.HasChated&lt;/code&gt; 检查。条件不满足时，&lt;code&gt;StartRefuseDialog()&lt;/code&gt; 按 &lt;code&gt;ChatType&lt;/code&gt; 切到拒绝分支，界面继续显示对应内容。&lt;/p&gt;
&lt;p&gt;对话结束时，&lt;code&gt;EndDialog()&lt;/code&gt; 把 &lt;code&gt;mainCharacter&lt;/code&gt; 写进 &lt;code&gt;ConversationHistoryManager&lt;/code&gt;。&lt;code&gt;ConversationHistoryManager&lt;/code&gt; 用 &lt;code&gt;HashSet&amp;lt;CharacterSO&amp;gt;&lt;/code&gt; 记录已触发角色，&lt;code&gt;ItemHistoryManager&lt;/code&gt; 用 &lt;code&gt;Dictionary&amp;lt;ItemSO, int&amp;gt;&lt;/code&gt; 记录物品累计数量。历史系统服务条件判断。任务节点、分支对话和拒绝对话都从历史系统读取结果。&lt;/p&gt;
&lt;p&gt;选项按钮纳入 &lt;code&gt;DialogManager&lt;/code&gt;。&lt;code&gt;ShowChoices()&lt;/code&gt; 遍历 &lt;code&gt;nextDialogOptions&lt;/code&gt;，把选项文本写进按钮，再通过 &lt;code&gt;onClick&lt;/code&gt; 注册进入下一节点。主分支、拒绝分支、一次性对话和普通默认对话共用同一套结构。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 20 日到 2026 年 4 月 24 日：任务系统成型&lt;/h2&gt;
&lt;p&gt;任务系统主体是 &lt;code&gt;QuestManager&lt;/code&gt;。类内部维护 &lt;code&gt;Dictionary&amp;lt;QuestSO, QuestProgressData&amp;gt;&lt;/code&gt;，每个任务对应一个状态和一张目标进度表。&lt;code&gt;QuestProgressData&lt;/code&gt; 使用 &lt;code&gt;Dictionary&amp;lt;QuestObjective, int&amp;gt;&lt;/code&gt; 保存目标当前值。任务板打开时，&lt;code&gt;OnReFreshQuestState()&lt;/code&gt; 先初始化进度表，再刷新 &lt;code&gt;QuestLogSlot&lt;/code&gt;。任务板为空时，详情页与提示页切到空任务状态。&lt;/p&gt;
&lt;p&gt;任务状态流转由 &lt;code&gt;QuestStateChanged()&lt;/code&gt; 控制。状态变化时，接取、放弃、完成按钮区域同步切换，&lt;code&gt;QuestLogUI&lt;/code&gt; 刷新目标文本。任务完成时，&lt;code&gt;RaiseRewardEvent()&lt;/code&gt; 遍历奖励列表，把奖励写进 &lt;code&gt;InventorySlotsStatsSO&lt;/code&gt;。奖励发放由事件进入库存更新流程，不直接改背包槽位。&lt;/p&gt;
&lt;p&gt;任务进度统计直接依赖历史系统。&lt;code&gt;UpdateObjectiveProgress()&lt;/code&gt; 在目标是物品时读取 &lt;code&gt;ItemHistoryManager&lt;/code&gt; 的累计数量，在目标是角色时读取 &lt;code&gt;ConversationHistoryManager&lt;/code&gt; 的对话记录。任务脚本不需要维护 NPC 交互细节。任务目标和对话历史、拾取记录共享同一套底层数据。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;QuestObjective&lt;/code&gt; 同时包含目标物品、目标角色和目标地点字段。地点统计接口已经留在数据结构中，地图触发点逻辑预留在该字段上。&lt;/p&gt;
&lt;h2&gt;2026 年 4 月 26 日到 2026 年 4 月 29 日：奖励、商店、UIManager 与 Addressables&lt;/h2&gt;
&lt;p&gt;奖励发放、商店、UI 路由和 Addressables 场景加载整理成同一条调用链。&lt;code&gt;QuestManager.RaiseRewardEvent()&lt;/code&gt; 把奖励发给库存系统，&lt;code&gt;ShopManager&lt;/code&gt; 接收商品列表并打开商店面板，&lt;code&gt;UIManager&lt;/code&gt; 负责面板互斥，场景链路由 &lt;code&gt;SceneChanger&lt;/code&gt; 和 Addressables 维持。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ShopManager&lt;/code&gt; 内部维护一般物品、武器、防具三张列表。&lt;code&gt;OnShopLoad()&lt;/code&gt; 接到 &lt;code&gt;ShopLoadEventSO&lt;/code&gt; 后，把列表保存到管理器，再打开商店 CanvasGroup。购买调用 &lt;code&gt;RaiseInventoryUpdateRequest(item, price, 1)&lt;/code&gt;。出售沿用同一接口，只把价格和数量改成负值。买卖逻辑共用同一条库存更新链路。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UIManager&lt;/code&gt; 在 &lt;code&gt;Update()&lt;/code&gt; 中读取 ESC、技能、属性、任务、对话、商店等输入，判断当前是否已有面板打开，再通过一组 &lt;code&gt;ToggleCanvasEventSO&lt;/code&gt; 广播目标状态。管理器不直接硬编码每个面板的开关。面板开关和互斥关系都经事件系统分发。场景切换事件进入时，&lt;code&gt;ResetCanvas()&lt;/code&gt; 把托管面板全部关掉，清空跨场景残留。&lt;/p&gt;
&lt;p&gt;Addressables 场景链路固定为统一顺序。场景加载、场景卸载、淡入淡出、玩家状态恢复按同一顺序执行，普通加载接口不混入该路径。场景调试路径和构建路径保持一致。&lt;/p&gt;
&lt;h2&gt;结果&lt;/h2&gt;
&lt;p&gt;场景切换、状态恢复、A*、NPC 行为、条件对话、任务进度、奖励发放、商店和 UI 管理纳入同一条主链。系统边界如下：场景切换用事件和 Addressables，状态恢复用 &lt;code&gt;DataManager&lt;/code&gt;，路径搜索用 A*，对话和任务读取历史系统，面板互斥由 &lt;code&gt;UIManager&lt;/code&gt; 统一处理。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;/posts/unity-arpg-project-intro/&quot;&gt;项目介绍：My ARPG&lt;/a&gt;&lt;/p&gt;
</content:encoded></item></channel></rss>