v0.1.25: 乾坤一统——MOD 系统首版(1040 全绿,金钟罩不漂)

【P0 修复(0.1.24 遗留)】worldGen.npcs defs 落档 + normalize 幂等重注册——读档后
动态家族(n-g-*)npcById 永命中;MOD 卸载后存档世界仍完整(存档世界永稳)

【MOD 系统四层】
- M2 内容层:modSchema.ts(ModPack 全 JSON:manifest+data{events/npcs/worldgen/pills/forges};
  modParse 纯解析校验 id/name/version/事件模板合法性)
- M3 管理器:modToPlugin(MOD→CotycPlugin 一等子类——插件持久化/双闸/启停/回滚全复用)
- M1 传输层:main IPC mods:scan/read(userData/mods/*.json|*.cotymod)+ preload + env.d.ts
  + store refreshMods/installModByName/installModText
- M4 UI:SettingsPanel「MOD 层」卡(扫描目录/候选列表/安装);内置示例包通路

【世界/插件协同】
- WorldGenPools 聚合词库池(默认不变→基准世界不变;reset() 供隔离);MOD 于新档参与生成
- items.ts 配方聚合注册表(PILL/FORGE base+扩展);PluginContext addPillRecipe/addForgeRecipe/addWorldGenPool

【边界(明注)】灾因/世界数值表注入归平衡版;脚本型 MOD 不做;MOD 只影响新档世界(老档不变形)

【测试】1040 全绿(46 套件):worldGen 存档 1 例 + mod-system 5 例(解析/转换/模板/依赖/基准指纹);
金钟罩 0.1.24 基线未漂(世界生成默认池不变);build 通过
This commit is contained in:
2026-08-23 16:29:29 +08:00
parent ec25bf92fc
commit 5d9c333c76
18 changed files with 364 additions and 21 deletions
+33 -1
View File
@@ -10,6 +10,7 @@ export default function SettingsPanel() {
const bump = useGameStore((s) => s.bump)
const slot = useGameStore((s) => s.slot)
const saveNow = useGameStore((s) => s.saveNow)
const modsList = useGameStore((s) => s.modsList)
const exportSave = useGameStore((s) => s.exportSave)
const importSave = useGameStore((s) => s.importSave)
const refreshSlots = useGameStore((s) => s.refreshSlots)
@@ -32,6 +33,37 @@ export default function SettingsPanel() {
return (
<div className="settings-wrap">
{/* ===== MOD 层:外部内容包(userData/mods/*.cotymod|json===== */}
<div className="card settings-card">
<div className="card-title">MOD </div>
<div className="help-text">
MOD <code>userData/mods/</code>*.cotymod / *.json
///线
</div>
<div style={{ display: 'flex', gap: 6, marginBottom: 6, flexWrap: 'wrap' }}>
<button className="btn btn-sm" onClick={() => { void useGameStore.getState().refreshMods(); setNextToast('已扫描 mods 目录。') }}> </button>
<span className="dim2"> {modsList.length} </span>
</div>
{modsList.length > 0 && (
<div className="plugin-grid">
{modsList.map((name) => (
<div key={name} className="plugin-row">
<div className="plugin-id">{name}</div>
<div className="plugin-info">
<span className="dim2" style={{ fontSize: '0.8rem' }}></span>
</div>
<div className="plugin-actions">
<button
className="btn btn-sm"
onClick={() => { void useGameStore.getState().installModByName(name) }}
></button>
</div>
</div>
))}
</div>
)}
</div>
{/* ===== 插件层:万物皆是插件的实证窗口 ===== */}
<div className="card settings-card">
<div className="card-title">manifest </div>
@@ -224,7 +256,7 @@ export default function SettingsPanel() {
· <br />
·
</div>
<div className="dim2" style={{ marginTop: 8 }}> 0.1.24 · Chronicle of the Immortal Clan</div>
<div className="dim2" style={{ marginTop: 8 }}> 0.1.25 · Chronicle of the Immortal Clan</div>
</div>
</div>
)