diff --git a/.tasks/2025-11-14_1_alchemy-web-render.md b/.tasks/2025-11-14_1_alchemy-web-render.md new file mode 100644 index 0000000..c370fbf --- /dev/null +++ b/.tasks/2025-11-14_1_alchemy-web-render.md @@ -0,0 +1,43 @@ +# 背景 +文件名:2025-11-14_1 +创建于:2025-11-14_00:37:03 +创建者:ASUS +主分支:main +任务分支:未创建 +Yolo模式:Off + +# 任务描述 +为 `WPSAlchemyGame.py` 中的炼金配方添加网页渲染,使网页可以查看全部炼金配方。 + +# 项目概览 +WPS 系统包含多个插件模块(例如炼金、背包、园艺等),基于 `WPSAPI` 统一框架运行,涉及数据库、背包物品与任务调度等组件。 + +# 分析 +- 当前仅在指令引导中展示炼金配方信息,缺少面向网页的统一渲染接口。 +- 需要了解 `WPSAPI` 以及与网页渲染相关的接口或模块,以确认扩展方式。 +- 需确认 `WPSAlchemyGame` 是否已有结构化配方数据可供复用。 + +# 提议的解决方案 +- 移除炼金系统中对园艺、水晶等外部模块的静态章节描述,只保留自身关注的内容。 +- 基于 `self._recipes` 动态生成“所有炼金配方”章节,遍历全部注册配方并汇总材料、成功/失败产物与成功率。 +- 可选地通过背包系统解析物品名称,不可用时回退展示 ID,确保纯粹依赖炼金持有的数据。 + +# 当前执行步骤:"2. 修改 WPSAlchemyGame 配方渲染" + +# 任务进度 +[2025-11-14_00:37:03] +- 已修改:.tasks/2025-11-14_1_alchemy-web-render.md +- 更改:创建任务文件并记录任务背景与初步分析 +- 原因:初始化炼金网页渲染任务 +- 阻碍因素:无 +- 状态:成功 + +[2025-11-14_00:51:30] +- 已修改:.tasks/2025-11-14_1_alchemy-web-render.md Plugins/WPSAlchemyGame.py +- 更改:确定移除跨系统章节并添加“所有炼金配方”方案,开始调整炼金系统渲染逻辑 +- 原因:确保炼金系统仅聚焦自身配方并支持完整网页展示 +- 阻碍因素:无 +- 状态:成功 + +# 最终审查 +待完成。 diff --git a/Plugins/WPSAlchemyGame.py b/Plugins/WPSAlchemyGame.py index c567f1d..cbdb146 100644 --- a/Plugins/WPSAlchemyGame.py +++ b/Plugins/WPSAlchemyGame.py @@ -163,37 +163,28 @@ class WPSAlchemyGame(WPSAPI): def collect_additional_sections(self) -> Sequence[GuideSection]: sections = list(super().collect_additional_sections()) - sections.append( - GuideSection( - title="基础配方", - entries=self._build_core_recipes(), - layout="grid", - section_id="alchemy-core", - description="系统内置的基础配方,可在没有额外模块时直接使用。", - ) - ) - garden_recipes = self._build_garden_wine_recipes() - if garden_recipes: + core_recipes = self._build_core_recipes() + if core_recipes: sections.append( GuideSection( - title="果酒配方", - entries=garden_recipes, + title="基础配方", + entries=core_recipes, layout="grid", - section_id="alchemy-garden", - description="菜园系统提供的果酒炼金配方,使用三份果实即可酿造果酒。", + section_id="alchemy-core", + description="系统内置的基础配方,可在没有额外模块时直接使用。", ) ) - crystal_recipes = self._build_crystal_chain_recipes() - if crystal_recipes: + all_recipes = self._build_all_recipe_entries() + if all_recipes: sections.append( GuideSection( - title="水晶链路", - entries=crystal_recipes, + title="所有炼金配方", + entries=all_recipes, layout="list", - section_id="alchemy-crystal", - description="水晶系统的多阶段炼金链路,最终可获得黑水晶核心。", + section_id="alchemy-all", + description="当前已注册的全部炼金配方列表。", ) ) @@ -226,84 +217,81 @@ class WPSAlchemyGame(WPSAPI): ) return entries - def _build_garden_wine_recipes(self) -> Sequence[GuideEntry]: - try: - from Plugins.WPSGardenSystem.garden_models import GARDEN_CROPS - except ImportError: + def _build_all_recipe_entries(self) -> Sequence[GuideEntry]: + if not self._recipes: return () - entries: List[GuideEntry] = [] - for crop in GARDEN_CROPS.values(): - if not crop.wine_item_id: - continue - items = [ - f"材料:{crop.fruit_id} × 3", - f"成功产物:{crop.wine_item_id}", - "失败产物:garden_item_rot_fruit", - "基础成功率:75%", - ] - entries.append( - GuideEntry( - title=f"{crop.display_name}果酒", - identifier=f"{crop.fruit_id} ×3", - description=f"使用 {crop.display_name} 的果实炼制同名果酒。", - category="果酒配方", - metadata={ - "果酒稀有度": crop.wine_tier or "rare", - }, - icon="🍷", - tags=(crop.tier.title(),), - details=[{"type": "list", "items": items}], - ) - ) - return entries - def _build_crystal_chain_recipes(self) -> Sequence[GuideEntry]: try: - from Plugins.WPSCrystalSystem.crystal_models import ( - DEFAULT_CRYSTAL_COLOR_MAP, - DEFAULT_CRYSTAL_EXCHANGE_ENTRIES, - ) - except ImportError: - return () + backpack: Optional[WPSBackpackSystem] = Architecture.Get(WPSBackpackSystem) + except Exception: # pylint: disable=broad-except + backpack = None + + name_cache: Dict[str, str] = {} + + def resolve_name(item_id: str) -> str: + if not item_id: + return item_id + if item_id in name_cache: + return name_cache[item_id] + display = item_id + if backpack is not None: + try: + definition = backpack._get_definition(item_id) # noqa: SLF001 + display = definition.name + except Exception: # pylint: disable=broad-except + display = item_id + name_cache[item_id] = display + return display + + def format_materials(materials: Tuple[str, str, str]) -> str: + counter = Counter(materials) + parts: List[str] = [] + for item_id in sorted(counter.keys()): + count = counter[item_id] + label = f"{resolve_name(item_id)}({item_id})" + if count > 1: + label += f" × {count}" + parts.append(label) + return " + ".join(parts) + entries: List[GuideEntry] = [] - for color_def in DEFAULT_CRYSTAL_COLOR_MAP.values(): - stage_details: List[str] = [] - for stage in color_def.chain_stages: - mats = " + ".join(stage.materials) - stage_details.append( - f"{stage.identifier}:{mats} → {stage.result_item}(成功率 {stage.base_success_rate*100:.0f}%)" - ) - stage_details.append( - f"等待阶段:消耗 {', '.join(f'{k}×{v}' for k, v in color_def.wait_stage.consumed_items.items())}," - f"耗时 {color_def.wait_stage.delay_minutes} 分钟" - ) - fusion = color_def.final_fusion - stage_details.append( - f"最终融合:{', '.join(fusion.materials)} → {fusion.result_item}(成功率 {fusion.base_success_rate*100:.0f}%)" - ) + for _materials_key, recipe in sorted( + self._recipes.items(), + key=lambda item: (item[1].success_item_id, item[0]), + ): + materials_text = format_materials(recipe.materials) + success_display = resolve_name(recipe.success_item_id) + fail_display = resolve_name(recipe.fail_item_id) + + details = [ + f"材料:{materials_text}", + f"成功产物:{success_display}({recipe.success_item_id})", + f"失败产物:{fail_display}({recipe.fail_item_id})", + ] + entries.append( GuideEntry( - title=color_def.display_name, - identifier=color_def.color_key, - description="水晶染色与融合的完整链路。", - category="水晶链路", - icon="💠", - details=[{"type": "list", "items": stage_details}], + title=success_display or recipe.success_item_id, + identifier=recipe.success_item_id, + description=f"{materials_text} → {success_display}({recipe.success_item_id})", + metadata={ + "成功率": f"{recipe.base_success_rate:.2%}", + "失败产物": f"{fail_display}({recipe.fail_item_id})", + }, + details=[ + { + "type": "list", + "items": [ + *details, + f"基础成功率:{recipe.base_success_rate:.2%}", + ], + } + ], ) ) - for exchange in DEFAULT_CRYSTAL_EXCHANGE_ENTRIES.values(): - items = ", ".join(f"{item_id}×{qty}" for item_id, qty in exchange.required_items.items()) - entries.append( - GuideEntry( - title=exchange.metadata.get("display_name", exchange.identifier), - identifier=exchange.identifier, - description=f"兑换奖励:{exchange.reward_item}", - category="水晶兑换", - icon="🔁", - details=[f"需求:{items}"], - ) - ) - return entries + + return tuple(entries) + @override def dependencies(self) -> List[type]: return [WPSAPI, WPSBackpackSystem, WPSConfigAPI, WPSFortuneSystem, WPSStoreSystem]