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:
@@ -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>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user