更新炼金配方网页渲染
This commit is contained in:
43
.tasks/2025-11-14_1_alchemy-web-render.md
Normal file
43
.tasks/2025-11-14_1_alchemy-web-render.md
Normal file
@@ -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
|
||||
- 更改:确定移除跨系统章节并添加“所有炼金配方”方案,开始调整炼金系统渲染逻辑
|
||||
- 原因:确保炼金系统仅聚焦自身配方并支持完整网页展示
|
||||
- 阻碍因素:无
|
||||
- 状态:成功
|
||||
|
||||
# 最终审查
|
||||
待完成。
|
||||
@@ -163,37 +163,28 @@ class WPSAlchemyGame(WPSAPI):
|
||||
|
||||
def collect_additional_sections(self) -> Sequence[GuideSection]:
|
||||
sections = list(super().collect_additional_sections())
|
||||
|
||||
core_recipes = self._build_core_recipes()
|
||||
if core_recipes:
|
||||
sections.append(
|
||||
GuideSection(
|
||||
title="基础配方",
|
||||
entries=self._build_core_recipes(),
|
||||
entries=core_recipes,
|
||||
layout="grid",
|
||||
section_id="alchemy-core",
|
||||
description="系统内置的基础配方,可在没有额外模块时直接使用。",
|
||||
)
|
||||
)
|
||||
|
||||
garden_recipes = self._build_garden_wine_recipes()
|
||||
if garden_recipes:
|
||||
all_recipes = self._build_all_recipe_entries()
|
||||
if all_recipes:
|
||||
sections.append(
|
||||
GuideSection(
|
||||
title="果酒配方",
|
||||
entries=garden_recipes,
|
||||
layout="grid",
|
||||
section_id="alchemy-garden",
|
||||
description="菜园系统提供的果酒炼金配方,使用三份果实即可酿造果酒。",
|
||||
)
|
||||
)
|
||||
|
||||
crystal_recipes = self._build_crystal_chain_recipes()
|
||||
if crystal_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]
|
||||
|
||||
Reference in New Issue
Block a user