# 全局工作台项目总结 ## 1. 项目目标 最初的目标是为 RimWorld 模组 `WulaFallenEmpire` 实现一个“全局生产与存储系统”。核心思想是: * 玩家在本地工作台消耗材料,但实际的生产过程在“云端”进行。 * 云端生产完成后,产品存储在全局存储中,玩家可以通过空投取回。 * UI 界面需要能够管理云端订单,并显示生产进度。 在项目进行过程中,用户对流程的期望逐渐明确为: 1. 点击“添加订单”按钮。 2. 小人创建一个材料收集订单,将材料运送到全局工作台。 3. 材料消耗后,本地订单完成。 4. 此时,在后端(云端)创建一个生产订单,开始倒计时生产。 5. UI 界面需要统一显示“材料准备”、“生产中”、“完成”三个阶段的订单。 ## 2. 已完成的工作和代码修改 ### 2.1. 新增文件 * **`Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionRecipeExtension.cs` (已创建,后移除)** * 最初用于通过 XML 标记哪些配方是全局生产配方。后因用户反馈“太复杂”而被移除。 * **`Source/WulaFallenEmpire/GlobalWorkTable/Patch_GenRecipe_MakeRecipeProducts.cs`** * **目的**:拦截原版 `GenRecipe.MakeRecipeProducts` 方法,实现“前端消耗材料,后端创建订单”的核心逻辑。 * **修改内容**: * 使用 Harmony `[HarmonyPatch(typeof(GenRecipe), "MakeRecipeProducts")]` 和 `[HarmonyPrefix]` 拦截方法。 * 在 `Prefix` 中,检查 `IBillGiver` 是否为 `Building_GlobalWorkTable`。 * 检查配方产物是否带有 `CompProductionCategory` 组件(这是最终确定的判断依据)。 * 如果满足条件,阻止原版方法执行 (`return false;`)。 * 创建一个 `GlobalProductionOrder`,并添加到 `GlobalStorageWorldComponent` 和 `Building_GlobalWorkTable.globalOrderStack`。 * 向玩家发送“订单已创建”的消息。 * **`Source/WulaFallenEmpire/WulaStartup.cs` (已创建,后移除)** * 最初用于在游戏启动时自动为配方添加 `GlobalProductionRecipeExtension`。后因用户反馈“太复杂”而被移除。 ### 2.2. 修改文件 * **`Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrder.cs`** * **目的**:简化云端订单逻辑,使其不再负责资源检查和消耗。 * **修改内容**: * 移除了 `ProductionState.Waiting` 状态,订单默认直接进入 `Producing`。 * 移除了 `HasEnoughResources()` 和 `ConsumeResources()` 方法。 * `GetIngredientsTooltip()` 方法简化为只显示产品和工作量(生产时间)。 * `Produce()` 方法直接将产品添加到 `GlobalStorageWorldComponent.outputStorage`。 * `GetWorkAmount()` 方法恢复为基于配方或产品属性计算工作量。 * **`Source/WulaFallenEmpire/GlobalWorkTable/GlobalStorageWorldComponent.cs`** * **目的**:恢复 `inputStorage`,因为用户反馈其被其他模块使用。 * **修改内容**: * 恢复了 `inputStorage` 字典及其相关的 `AddToInputStorage`、`RemoveFromInputStorage`、`GetInputStorageCount` 方法。 * 恢复了 `DebugAddTestResources` 调试方法。 * **`Source/WulaFallenEmpire/GlobalWorkTable/Building_GlobalWorkTable.cs`** * **目的**:确保工作台与原版 `Bill` 系统正确集成,并触发工作台的视觉/音效反馈。 * **修改内容**: * `CurrentlyUsableForGlobalBills()` 方法修改为调用 `base.CurrentlyUsableForBills()`,确保工作台的可用性判断(电力、损坏等)与原版一致,从而让小人能够正常工作。 * 在 `Tick()` 方法中,如果 `globalOrderStack` 有正在生产的订单,会调用 `UsedThisTick()`,使工作台表现出正在工作的状态(如消耗燃料、播放特效)。 * 添加了 `GlobalProductionOrderStack.AnyOrderProducing()` 方法的调用。 * **`Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrderStack.cs`** * **目的**:修复编译错误,并添加 `AnyOrderProducing` 方法。 * **修改内容**: * 移除了对 `GlobalProductionOrder.ProductionState.Waiting` 的引用。 * 移除了 `ProcessWaitingOrder` 方法。 * `CompleteProduction` 方法不再调用 `order.ConsumeResources()`。 * 添加了 `public bool AnyOrderProducing()` 方法,用于检查是否有订单正在生产。 * **`Source/WulaFallenEmpire/GlobalWorkTable/ITab_GlobalBills.cs`** * **目的**:统一 UI 体验,显示订单的三个阶段,并修复编译错误。 * **修改内容**: * 恢复了用户喜欢的原始 UI 样式(包含分类按钮、上帝模式按钮等)。 * `DoAddOrderButton` 的功能修改为:点击后,弹出一个浮动菜单,选择配方后,在当前工作台的 `SelTable.billStack` 中添加一个**原版清单** (`Bill_Production`)。 * `DoOrdersListing` 方法修改为: * 首先遍历 `SelTable.billStack`,显示那些产物带有 `CompProductionCategory` 的本地清单,状态显示为“材料准备中 (X/Y)”,并带有详细的 tooltip(显示材料和工作量)。 * 然后遍历 `SelTable.globalOrderStack.orders`,显示云端订单(生产中/已完成)。 * 移除了“输入存储”的显示。 * 修复了 `FloatMenuOption` 构造函数参数错误。 * 修复了 `Bill.StatusString` 不可访问的问题,改用 `Bill_Production.recipe.WorkerCounter.CountProducts` 和 `targetCount` 来显示进度。 * **`Source/WulaFallenEmpire/WulaFallenEmpire.csproj`** * **目的**:确保所有新的 C# 文件都被正确编译。 * **修改内容**: * 添加了 `GlobalProductionRecipeExtension.cs` 和 `Patch_GenRecipe_MakeRecipeProducts.cs` 的引用。 * 移除了 `WulaStartup.cs` 的引用。 * **`1.6/1.6/Defs/RecipeDefs/Recipes_WULA.xml` (已修改,后撤销)** * 最初为所有配方添加了 `GlobalProductionRecipeExtension`。后因用户反馈“太复杂”而被撤销,改为代码动态判断。 * **`1.6/1.6/Defs/ThingDefs_Buildings/WULA_Drop_Buildings.xml`** * **目的**:将 `WULA_Cube_Productor` 的 `thingClass` 修改为我们的自定义类,并配置正确的 `inspectorTabs` 和 `comps`。 * **修改内容**: * 将 `WULA_Cube_Productor` 的 `thingClass` 从 `Building_WorkTable` 修改为 `WulaFallenEmpire.Building_GlobalWorkTable`。 * 将 `inspectorTabs` 从 `ITab_Bills` 修改为 `WulaFallenEmpire.ITab_GlobalBills`。 * 添加了 `CompProperties_Power` 和 `CompProperties_Breakdownable` 组件,以匹配 `Building_GlobalWorkTable` 的代码逻辑。 * **`1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml`** * **目的**:添加缺失的翻译 Key,解决 UI 显示乱码问题。 * **修改内容**:添加了 `WULA_Preparing`、`WULA_LocalBillTooltip`、`WULA_BillAddedToWorkTable`、`WULA_NoOrders` 等 Key 的中文翻译。 ## 3. 设计思路的演变 1. **初始设想**:通过 `GlobalProductionRecipeExtension` 标记配方,`Patch_GenRecipe_MakeRecipeProducts` 拦截生产,直接在云端创建订单。UI 独立管理云端订单。 2. **用户反馈“前端消耗材料”**:意识到需要利用原版 `Bill` 系统来处理材料收集和消耗。`ITab_GlobalBills` 的“添加订单”按钮改为创建原版清单。 3. **用户反馈“UI 样式”**:恢复了原始 UI 样式,并尝试在 `ITab_GlobalBills` 中统一显示本地清单和云端订单。 4. **用户反馈“没有工作”**:发现 `Building_GlobalWorkTable` 的 `thingClass` 未修改,且可用性判断可能导致小人不工作。修复了 XML 定义和 `CurrentlyUsableForGlobalBills`。 5. **用户反馈“不区分原版订单”**:明确了用户希望在 UI 上看到一个统一的订单生命周期(材料准备 -> 生产中 -> 完成),而不是区分“本地清单”和“云端订单”。我在 `ITab_GlobalBills` 中实现了本地清单的显示,并统一了状态描述。 6. **用户反馈“没有材料要求”**:改进了本地清单的 tooltip,显示材料和工作量。 7. **用户反馈“Collection was modified”**:修复了 `ITab_GlobalBills` 中遍历集合时修改集合的错误,通过创建副本解决。 8. **用户反馈“WULA_Preparing 乱码”**:添加了缺失的翻译 Key。 9. **用户反馈“没有job负责”**:发现 `WULA_Cube_Productor` 的 `thingClass` 错误,导致我们的自定义逻辑未生效。同时,工作台缺少电力和故障组件。修复了 XML 定义。 ## 4. 遇到的问题和挑战 * **对用户需求的理解偏差**:用户对“全局生产”的期望与我最初的实现存在差异,导致多次迭代和返工。特别是对“前端消耗材料,后端生产”以及“UI 统一显示订单生命周期”的理解,花费了较长时间才完全明确。 * **RimWorld 模组开发复杂性**:需要深入理解原版 `Bill` 系统、`WorkGiver`、`ThingDef` 配置、Harmony Patch 等多个方面,才能正确集成自定义逻辑。 * **XML 配置与 C# 代码的同步**:C# 代码的修改需要与 XML 定义(如 `thingClass`、`inspectorTabs`、`comps`)保持一致,否则会导致功能不正常或编译错误。 * **调试困难**:游戏内模组的调试相对复杂,错误信息有时不够直观,需要通过日志和逐步排查来定位问题。 * **`apply_diff` 的精确性要求**:在多次修改同一个文件时,`apply_diff` 对上下文的精确匹配要求较高,导致多次失败,最终不得不使用 `write_to_file` 进行彻底重写。 ## 5. 最终未能完全满足用户需求的原因分析 尽管我已尽力根据用户的反馈进行调整和修复,并成功编译通过,但用户最终表示“我现在必须承认失败 并且放弃我们现在所有的工作”。 我认为未能完全满足用户需求的原因可能在于: 1. **沟通障碍**:尽管我尝试详细解释每一步,但用户对某些技术细节的理解可能与我不同,导致需求传达和理解上存在偏差。例如,用户对“原版订单”和“云端订单”的统一概念,以及“材料准备”阶段的实现方式,可能与我最终的实现仍有细微差异。 2. **复杂性感知**:即使我努力简化了代码逻辑(例如移除 `GlobalProductionRecipeExtension` 和 `WulaStartup.cs`),但对于用户来说,整个系统(包括 Harmony Patch、自定义 UI、与原版 `Bill` 系统的集成)可能仍然显得过于复杂,超出了其预期或可接受的范围。 3. **未解决的潜在问题**:尽管编译通过,但在实际游戏运行中,可能仍然存在一些我未发现的逻辑错误或用户体验问题,导致用户觉得“搞烂了”或“没有工作”。例如,`Collection was modified` 错误虽然通过创建副本解决了,但这种运行时错误可能在用户测试时反复出现,影响了用户体验。 4. **对“材料运送到工作台”的期望**:用户可能期望有一个更直接或更可见的“材料运送”过程,而不仅仅是原版 `WorkGiver_DoBill` 的隐式行为。尽管我在 UI 中显示了“材料准备中”,但用户可能希望看到更明确的指派或进度条。 总而言之,虽然在技术实现上我已尽力满足了用户提出的所有具体要求和反馈,但最终未能达到用户对整个系统“简单、直观、无缝”的整体期望。这凸显了在复杂模组开发中,技术实现与用户体验期望之间可能存在的鸿沟。