modwright 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +35 -0
- package/README.md +212 -0
- package/assets/claude/agents/mw-explore.md +46 -0
- package/assets/claude/agents/mw-fixture.md +33 -0
- package/assets/claude/agents/mw-rule-author.md +51 -0
- package/assets/claude/agents/mw-scaffold-author.md +48 -0
- package/assets/claude/skills/mw-author.md +59 -0
- package/assets/claude/skills/mw-new-item.md +51 -0
- package/assets/claude/skills/mw-new-spell.md +50 -0
- package/assets/claude/skills/mw-scaffold.md +59 -0
- package/assets/claude/skills/mw-ship.md +57 -0
- package/assets/claude/skills/mw-validate.md +51 -0
- package/assets/claude/skills/mw-verify.md +59 -0
- package/assets/nivalisnights/extract_resources.py +177 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Config.json +5 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapClient.lua +55 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapServer.lua +81 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Log.lua +96 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Probes.lua +1038 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/ProbesClient.lua +74 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Protocol.lua +985 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Watch.lua +175 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/meta.lsx +45 -0
- package/bridges/bg3-se/README.md +99 -0
- package/bridges/bg3-se/bridge.json +68 -0
- package/bridges/cp2077-cet/ModWrightBridge/init.lua +375 -0
- package/bridges/cp2077-cet/ModWrightBridge/probes.lua +1104 -0
- package/bridges/cp2077-cet/ModWrightBridge/protocol.lua +1306 -0
- package/bridges/cp2077-cet/README.md +165 -0
- package/bridges/cp2077-cet/bridge.json +53 -0
- package/dist/core/bridge/arm.js +175 -0
- package/dist/core/bridge/cet-console.js +26 -0
- package/dist/core/bridge/cet-log.js +362 -0
- package/dist/core/bridge/index.js +11 -0
- package/dist/core/bridge/locate.js +35 -0
- package/dist/core/bridge/paths.js +34 -0
- package/dist/core/bridge/pending.js +89 -0
- package/dist/core/bridge/poll.js +155 -0
- package/dist/core/bridge/stage.js +100 -0
- package/dist/core/bridge/status.js +97 -0
- package/dist/core/bridge/types.js +145 -0
- package/dist/core/bridge/validate.js +107 -0
- package/dist/core/build/index.js +6 -0
- package/dist/core/build/manifest.js +47 -0
- package/dist/core/build/paths.js +32 -0
- package/dist/core/build/run.js +342 -0
- package/dist/core/build/stage.js +265 -0
- package/dist/core/build/steps/bg3.js +129 -0
- package/dist/core/build/steps/core.js +195 -0
- package/dist/core/build/steps/cyberpunk.js +95 -0
- package/dist/core/build/steps/listing.js +35 -0
- package/dist/core/build/types.js +13 -0
- package/dist/core/build/zip.js +148 -0
- package/dist/core/compat/check.js +113 -0
- package/dist/core/compat/pe.js +220 -0
- package/dist/core/compat/types.js +1 -0
- package/dist/core/compat/version.js +70 -0
- package/dist/core/deploy/guards.js +292 -0
- package/dist/core/deploy/index.js +5 -0
- package/dist/core/deploy/plan.js +696 -0
- package/dist/core/deploy/reload-apply.js +361 -0
- package/dist/core/deploy/reload.js +358 -0
- package/dist/core/deploy/sources.js +169 -0
- package/dist/core/deploy/types.js +1 -0
- package/dist/core/epic.js +54 -0
- package/dist/core/fsutil.js +191 -0
- package/dist/core/home.js +70 -0
- package/dist/core/knowledge/facts.js +229 -0
- package/dist/core/knowledge/index.js +4 -0
- package/dist/core/knowledge/search.js +112 -0
- package/dist/core/knowledge/store.js +123 -0
- package/dist/core/knowledge/types.js +1 -0
- package/dist/core/ledger/check.js +42 -0
- package/dist/core/ledger/hooks.js +80 -0
- package/dist/core/ledger/index.js +7 -0
- package/dist/core/ledger/query.js +17 -0
- package/dist/core/ledger/record.js +84 -0
- package/dist/core/ledger/status.js +53 -0
- package/dist/core/ledger/store.js +98 -0
- package/dist/core/ledger/types.js +108 -0
- package/dist/core/logs/index.js +4 -0
- package/dist/core/logs/registry.js +50 -0
- package/dist/core/logs/scan.js +195 -0
- package/dist/core/logs/triage.js +160 -0
- package/dist/core/logs/types.js +1 -0
- package/dist/core/lsx.js +10 -0
- package/dist/core/lz4.js +66 -0
- package/dist/core/mods.js +229 -0
- package/dist/core/process.js +49 -0
- package/dist/core/project/build-steps.js +83 -0
- package/dist/core/project/describe.js +74 -0
- package/dist/core/project/index.js +5 -0
- package/dist/core/project/load.js +146 -0
- package/dist/core/project/schema.js +264 -0
- package/dist/core/project/types.js +3 -0
- package/dist/core/prompts.js +72 -0
- package/dist/core/registry.js +35 -0
- package/dist/core/safety/backup.js +206 -0
- package/dist/core/safety/execute.js +188 -0
- package/dist/core/safety/index.js +5 -0
- package/dist/core/safety/plan.js +122 -0
- package/dist/core/safety/restore.js +172 -0
- package/dist/core/safety/types.js +1 -0
- package/dist/core/scaffold/bootstrap.js +7 -0
- package/dist/core/scaffold/catalog.js +28 -0
- package/dist/core/scaffold/claude-assets.js +271 -0
- package/dist/core/scaffold/collisions.js +64 -0
- package/dist/core/scaffold/emit.js +356 -0
- package/dist/core/scaffold/engine.js +680 -0
- package/dist/core/scaffold/ids.js +78 -0
- package/dist/core/scaffold/index.js +10 -0
- package/dist/core/scaffold/jsonpath.js +121 -0
- package/dist/core/scaffold/load.js +81 -0
- package/dist/core/scaffold/render.js +85 -0
- package/dist/core/scaffold/sequence.js +396 -0
- package/dist/core/scaffold/types.js +309 -0
- package/dist/core/steam.js +63 -0
- package/dist/core/surfaceutil.js +36 -0
- package/dist/core/testplan/check.js +67 -0
- package/dist/core/testplan/index.js +5 -0
- package/dist/core/testplan/load.js +100 -0
- package/dist/core/testplan/registry.js +317 -0
- package/dist/core/testplan/run.js +389 -0
- package/dist/core/testplan/types.js +82 -0
- package/dist/core/text/converters/bg3.js +50 -0
- package/dist/core/text/converters/cyberpunk.js +36 -0
- package/dist/core/text/converters/index.js +261 -0
- package/dist/core/text/diff/cr2w.js +180 -0
- package/dist/core/text/diff/index.js +16 -0
- package/dist/core/text/diff/loca.js +43 -0
- package/dist/core/text/diff/lsx.js +126 -0
- package/dist/core/text/handles.js +86 -0
- package/dist/core/text/index.js +6 -0
- package/dist/core/text/json.js +46 -0
- package/dist/core/text/templates/cache.js +71 -0
- package/dist/core/text/templates/index.js +3 -0
- package/dist/core/text/templates/library.js +245 -0
- package/dist/core/text/templates/types.js +51 -0
- package/dist/core/text/toolchain.js +16 -0
- package/dist/core/text/types.js +1 -0
- package/dist/core/text/validate.js +149 -0
- package/dist/core/text/xml.js +58 -0
- package/dist/core/toolchain/datafetch.js +151 -0
- package/dist/core/toolchain/env.js +63 -0
- package/dist/core/toolchain/features.js +170 -0
- package/dist/core/toolchain/index.js +8 -0
- package/dist/core/toolchain/install.js +191 -0
- package/dist/core/toolchain/locate.js +275 -0
- package/dist/core/toolchain/remember.js +84 -0
- package/dist/core/toolchain/run.js +318 -0
- package/dist/core/toolchain/specs.js +351 -0
- package/dist/core/toolchain/types.js +1 -0
- package/dist/core/types.js +1 -0
- package/dist/core/userconfig.js +66 -0
- package/dist/core/validate/context.js +139 -0
- package/dist/core/validate/index.js +5 -0
- package/dist/core/validate/registry.js +58 -0
- package/dist/core/validate/run.js +131 -0
- package/dist/core/validate/suppressions.js +91 -0
- package/dist/core/validate/types.js +2 -0
- package/dist/core/yamledit.js +51 -0
- package/dist/index.js +389 -0
- package/dist/server.js +1914 -0
- package/dist/surfaces/baldursgate3/compat.js +164 -0
- package/dist/surfaces/baldursgate3/identity.js +110 -0
- package/dist/surfaces/baldursgate3/index/build.js +331 -0
- package/dist/surfaces/baldursgate3/index/index.js +17 -0
- package/dist/surfaces/baldursgate3/index/info.js +40 -0
- package/dist/surfaces/baldursgate3/index/parsers/loca.js +41 -0
- package/dist/surfaces/baldursgate3/index/parsers/lsx.js +137 -0
- package/dist/surfaces/baldursgate3/index/parsers/stats.js +45 -0
- package/dist/surfaces/baldursgate3/index/parsers/treasuretable.js +57 -0
- package/dist/surfaces/baldursgate3/index/parsers/xmlutil.js +142 -0
- package/dist/surfaces/baldursgate3/index/queries.js +327 -0
- package/dist/surfaces/baldursgate3/index/schema.js +62 -0
- package/dist/surfaces/baldursgate3/index.js +3 -0
- package/dist/surfaces/baldursgate3/logs.js +278 -0
- package/dist/surfaces/baldursgate3/modsettings.js +115 -0
- package/dist/surfaces/baldursgate3/pak.js +153 -0
- package/dist/surfaces/baldursgate3/settings.js +49 -0
- package/dist/surfaces/baldursgate3/surface.js +232 -0
- package/dist/surfaces/baldursgate3/validators/bridge.js +7 -0
- package/dist/surfaces/baldursgate3/validators/files.js +476 -0
- package/dist/surfaces/baldursgate3/validators/items.js +1001 -0
- package/dist/surfaces/baldursgate3/validators/progression.js +734 -0
- package/dist/surfaces/baldursgate3/validators/stats.js +1076 -0
- package/dist/surfaces/baldursgate3/validators/story.js +790 -0
- package/dist/surfaces/baldursgate3/validators/templates.js +7 -0
- package/dist/surfaces/cyberpunk2077/compat.js +223 -0
- package/dist/surfaces/cyberpunk2077/index/build.js +231 -0
- package/dist/surfaces/cyberpunk2077/index/index.js +17 -0
- package/dist/surfaces/cyberpunk2077/index/info.js +51 -0
- package/dist/surfaces/cyberpunk2077/index/model.js +52 -0
- package/dist/surfaces/cyberpunk2077/index/parsers/tweak.js +483 -0
- package/dist/surfaces/cyberpunk2077/index/parsers/tweakxl-yaml.js +183 -0
- package/dist/surfaces/cyberpunk2077/index/queries.js +504 -0
- package/dist/surfaces/cyberpunk2077/index/resource.js +135 -0
- package/dist/surfaces/cyberpunk2077/index/schema.js +90 -0
- package/dist/surfaces/cyberpunk2077/index.js +3 -0
- package/dist/surfaces/cyberpunk2077/logs.js +742 -0
- package/dist/surfaces/cyberpunk2077/paths.js +12 -0
- package/dist/surfaces/cyberpunk2077/surface.js +218 -0
- package/dist/surfaces/cyberpunk2077/validators/bridge.js +7 -0
- package/dist/surfaces/cyberpunk2077/validators/cr2w.js +349 -0
- package/dist/surfaces/cyberpunk2077/validators/garments.js +1181 -0
- package/dist/surfaces/cyberpunk2077/validators/mesh.js +338 -0
- package/dist/surfaces/cyberpunk2077/validators/modsettings.js +120 -0
- package/dist/surfaces/cyberpunk2077/validators/packaging.js +463 -0
- package/dist/surfaces/cyberpunk2077/validators/red4ext.js +318 -0
- package/dist/surfaces/cyberpunk2077/validators/redscript.js +193 -0
- package/dist/surfaces/cyberpunk2077/validators/templates.js +7 -0
- package/dist/surfaces/cyberpunk2077/validators/tweaks.js +768 -0
- package/dist/surfaces/cyberpunk2077/validators/vehicles.js +531 -0
- package/dist/surfaces/cyberpunk2077/validators/xl.js +308 -0
- package/dist/surfaces/eldenring/binders.js +111 -0
- package/dist/surfaces/eldenring/compat.js +166 -0
- package/dist/surfaces/eldenring/dcx.js +49 -0
- package/dist/surfaces/eldenring/index.js +13 -0
- package/dist/surfaces/eldenring/loaders.js +132 -0
- package/dist/surfaces/eldenring/logs.js +67 -0
- package/dist/surfaces/eldenring/paramdef.js +256 -0
- package/dist/surfaces/eldenring/params.js +129 -0
- package/dist/surfaces/eldenring/surface.js +121 -0
- package/dist/surfaces/eldenring/tools.js +52 -0
- package/dist/surfaces/eldenring/validators/binders.js +193 -0
- package/dist/surfaces/eldenring/validators/packages.js +159 -0
- package/dist/surfaces/eldenring/validators/params.js +334 -0
- package/dist/surfaces/eldenring/validators/profiles.js +287 -0
- package/dist/surfaces/index.js +34 -0
- package/dist/surfaces/nivalisnights/compat.js +229 -0
- package/dist/surfaces/nivalisnights/index/build.js +310 -0
- package/dist/surfaces/nivalisnights/index/index.js +5 -0
- package/dist/surfaces/nivalisnights/index/queries.js +231 -0
- package/dist/surfaces/nivalisnights/index.js +4 -0
- package/dist/surfaces/nivalisnights/logs.js +473 -0
- package/dist/surfaces/nivalisnights/surface.js +195 -0
- package/dist/surfaces/skyrimse/archives.js +229 -0
- package/dist/surfaces/skyrimse/compat.js +163 -0
- package/dist/surfaces/skyrimse/index.js +12 -0
- package/dist/surfaces/skyrimse/loadorder.js +174 -0
- package/dist/surfaces/skyrimse/logs.js +241 -0
- package/dist/surfaces/skyrimse/plugins.js +149 -0
- package/dist/surfaces/skyrimse/records.js +94 -0
- package/dist/surfaces/skyrimse/surface.js +240 -0
- package/dist/surfaces/skyrimse/validators/archive-records.js +165 -0
- package/dist/surfaces/skyrimse/validators/archives.js +110 -0
- package/dist/surfaces/skyrimse/validators/plugins.js +374 -0
- package/dist/surfaces/skyrimse/validators/records.js +117 -0
- package/dist/surfaces/stardewvalley/compat.js +190 -0
- package/dist/surfaces/stardewvalley/config.js +42 -0
- package/dist/surfaces/stardewvalley/contentpatcher.js +203 -0
- package/dist/surfaces/stardewvalley/index/index.js +229 -0
- package/dist/surfaces/stardewvalley/index/wiki.js +190 -0
- package/dist/surfaces/stardewvalley/index.js +12 -0
- package/dist/surfaces/stardewvalley/logs.js +307 -0
- package/dist/surfaces/stardewvalley/mods.js +182 -0
- package/dist/surfaces/stardewvalley/surface.js +244 -0
- package/dist/surfaces/stardewvalley/validators/content.js +321 -0
- package/dist/surfaces/stardewvalley/validators/fields.js +147 -0
- package/dist/surfaces/stardewvalley/validators/loadorder.js +69 -0
- package/dist/surfaces/stardewvalley/validators/manifest.js +221 -0
- package/dist/surfaces/subnautica2/compat.js +138 -0
- package/dist/surfaces/subnautica2/index.js +5 -0
- package/dist/surfaces/subnautica2/logs.js +129 -0
- package/dist/surfaces/subnautica2/paks.js +173 -0
- package/dist/surfaces/subnautica2/surface.js +151 -0
- package/dist/surfaces/subnautica2/validators/packaging.js +298 -0
- package/dist/surfaces/valheim/compat.js +171 -0
- package/dist/surfaces/valheim/index/index.js +301 -0
- package/dist/surfaces/valheim/index/tables.js +103 -0
- package/dist/surfaces/valheim/index.js +11 -0
- package/dist/surfaces/valheim/logs.js +197 -0
- package/dist/surfaces/valheim/packaging.js +131 -0
- package/dist/surfaces/valheim/plugins.js +270 -0
- package/dist/surfaces/valheim/references.js +121 -0
- package/dist/surfaces/valheim/surface.js +223 -0
- package/dist/surfaces/valheim/validators/packaging.js +218 -0
- package/dist/surfaces/valheim/validators/plugins.js +287 -0
- package/dist/surfaces/valheim/validators/references.js +169 -0
- package/knowledge/baldursgate3/animations.gr2.yaml +166 -0
- package/knowledge/baldursgate3/audio.voice.yaml +182 -0
- package/knowledge/baldursgate3/audio.wwise.yaml +104 -0
- package/knowledge/baldursgate3/charactercreation.heads-hair.yaml +193 -0
- package/knowledge/baldursgate3/communitylibrary.shared-content.yaml +129 -0
- package/knowledge/baldursgate3/compatibilityframework.api.yaml +176 -0
- package/knowledge/baldursgate3/crash.causes.yaml +90 -0
- package/knowledge/baldursgate3/dialogue.dialogbank.yaml +120 -0
- package/knowledge/baldursgate3/dialogue.files.yaml +236 -0
- package/knowledge/baldursgate3/dialogue.osiris-goals.yaml +386 -0
- package/knowledge/baldursgate3/dialogue.yaml +122 -0
- package/knowledge/baldursgate3/feats.classes.yaml +164 -0
- package/knowledge/baldursgate3/items.cloth-physics.yaml +167 -0
- package/knowledge/baldursgate3/items.roottemplates.yaml +320 -0
- package/knowledge/baldursgate3/items.visualbank.yaml +628 -0
- package/knowledge/baldursgate3/journal.quests.yaml +214 -0
- package/knowledge/baldursgate3/loadorder.modsettings.yaml +128 -0
- package/knowledge/baldursgate3/localization.handles.yaml +92 -0
- package/knowledge/baldursgate3/misc.encoding-and-practice.yaml +111 -0
- package/knowledge/baldursgate3/origins.companions.yaml +144 -0
- package/knowledge/baldursgate3/osiris.signatures.yaml +211 -0
- package/knowledge/baldursgate3/packaging.meta.yaml +155 -0
- package/knowledge/baldursgate3/packaging.paks.yaml +79 -0
- package/knowledge/baldursgate3/process.launch.yaml +34 -0
- package/knowledge/baldursgate3/progressions.yaml +92 -0
- package/knowledge/baldursgate3/publishing.modio-nexus.yaml +170 -0
- package/knowledge/baldursgate3/publishing.toolkit-modio.yaml +135 -0
- package/knowledge/baldursgate3/races.progression.yaml +228 -0
- package/knowledge/baldursgate3/scriptextender.console.yaml +257 -0
- package/knowledge/baldursgate3/scriptextender.yaml +252 -0
- package/knowledge/baldursgate3/stats.boosts.yaml +293 -0
- package/knowledge/baldursgate3/stats.equipment-kits.yaml +69 -0
- package/knowledge/baldursgate3/stats.interrupts.yaml +45 -0
- package/knowledge/baldursgate3/stats.itemcombos.yaml +65 -0
- package/knowledge/baldursgate3/stats.spells.yaml +293 -0
- package/knowledge/baldursgate3/stats.weapons.yaml +210 -0
- package/knowledge/baldursgate3/toolchain.divine.yaml +179 -0
- package/knowledge/baldursgate3/toolchain.lslib-formats.yaml +242 -0
- package/knowledge/baldursgate3/toolkit.levels.yaml +177 -0
- package/knowledge/baldursgate3/ui.icons-atlas.yaml +78 -0
- package/knowledge/baldursgate3/ui.icons.yaml +412 -0
- package/knowledge/baldursgate3/ui.mcm.yaml +161 -0
- package/knowledge/baldursgate3/vfx.materials.yaml +174 -0
- package/knowledge/baldursgate3/visuals.characterfix.yaml +73 -0
- package/knowledge/cyberpunk2077/animations.anims.yaml +118 -0
- package/knowledge/cyberpunk2077/anims.archivexl.yaml +163 -0
- package/knowledge/cyberpunk2077/anims.authoring.yaml +579 -0
- package/knowledge/cyberpunk2077/anims.encoder.yaml +156 -0
- package/knowledge/cyberpunk2077/anims.graph.yaml +629 -0
- package/knowledge/cyberpunk2077/anims.method.yaml +360 -0
- package/knowledge/cyberpunk2077/anims.pipeline.yaml +352 -0
- package/knowledge/cyberpunk2077/anims.roundtrip.yaml +222 -0
- package/knowledge/cyberpunk2077/anims.sets.yaml +176 -0
- package/knowledge/cyberpunk2077/archivexl.bodytypes.yaml +149 -0
- package/knowledge/cyberpunk2077/archivexl.dynamic-appearances.yaml +218 -0
- package/knowledge/cyberpunk2077/archivexl.manifest.yaml +214 -0
- package/knowledge/cyberpunk2077/audio.events.yaml +168 -0
- package/knowledge/cyberpunk2077/audio.sounds.yaml +164 -0
- package/knowledge/cyberpunk2077/audio.voicesets.yaml +146 -0
- package/knowledge/cyberpunk2077/cet.sandbox.yaml +219 -0
- package/knowledge/cyberpunk2077/clothing.garments.yaml +283 -0
- package/knowledge/cyberpunk2077/clothing.refits.yaml +215 -0
- package/knowledge/cyberpunk2077/codeware.overview.yaml +111 -0
- package/knowledge/cyberpunk2077/codeware.systems.yaml +192 -0
- package/knowledge/cyberpunk2077/drones.combat.yaml +416 -0
- package/knowledge/cyberpunk2077/drones.control.yaml +552 -0
- package/knowledge/cyberpunk2077/entities.appearance.yaml +166 -0
- package/knowledge/cyberpunk2077/equipmentex.slots.yaml +151 -0
- package/knowledge/cyberpunk2077/fx.effects.yaml +246 -0
- package/knowledge/cyberpunk2077/fx.lights.yaml +171 -0
- package/knowledge/cyberpunk2077/hair.modding.yaml +145 -0
- package/knowledge/cyberpunk2077/items.wiring.yaml +246 -0
- package/knowledge/cyberpunk2077/loadorder.archives.yaml +71 -0
- package/knowledge/cyberpunk2077/mesh.blender.yaml +209 -0
- package/knowledge/cyberpunk2077/nativedb.dump.yaml +98 -0
- package/knowledge/cyberpunk2077/npc.appearance.yaml +275 -0
- package/knowledge/cyberpunk2077/npc.behaviour.yaml +128 -0
- package/knowledge/cyberpunk2077/npc.locomotion.yaml +490 -0
- package/knowledge/cyberpunk2077/packaging.deploy.yaml +175 -0
- package/knowledge/cyberpunk2077/packaging.variants.yaml +176 -0
- package/knowledge/cyberpunk2077/player.control.yaml +918 -0
- package/knowledge/cyberpunk2077/process.assetbuild.yaml +154 -0
- package/knowledge/cyberpunk2077/process.lessons.yaml +276 -0
- package/knowledge/cyberpunk2077/quests.minor.yaml +46 -0
- package/knowledge/cyberpunk2077/quests.scenes.yaml +282 -0
- package/knowledge/cyberpunk2077/quickhacks.tiers.yaml +41 -0
- package/knowledge/cyberpunk2077/red4ext.api.yaml +645 -0
- package/knowledge/cyberpunk2077/red4ext.plugins.yaml +124 -0
- package/knowledge/cyberpunk2077/redhottools.hotreload.yaml +245 -0
- package/knowledge/cyberpunk2077/redscript.compile-log.yaml +76 -0
- package/knowledge/cyberpunk2077/redscript.modules.yaml +118 -0
- package/knowledge/cyberpunk2077/toolchain.wolvenkit.yaml +163 -0
- package/knowledge/cyberpunk2077/tweakdb.loot-recipes.yaml +184 -0
- package/knowledge/cyberpunk2077/tweakdb.melee.yaml +352 -0
- package/knowledge/cyberpunk2077/tweakdb.weapons.yaml +325 -0
- package/knowledge/cyberpunk2077/tweakxl.hotreload.yaml +151 -0
- package/knowledge/cyberpunk2077/tweakxl.yaml-syntax.yaml +208 -0
- package/knowledge/cyberpunk2077/ui.icons.yaml +259 -0
- package/knowledge/cyberpunk2077/ui.inkatlas.yaml +81 -0
- package/knowledge/cyberpunk2077/ui.modsettings.yaml +204 -0
- package/knowledge/cyberpunk2077/vehicles.control.yaml +475 -0
- package/knowledge/cyberpunk2077/vehicles.dashboard-ui.yaml +203 -0
- package/knowledge/cyberpunk2077/vehicles.entities.yaml +195 -0
- package/knowledge/cyberpunk2077/vehicles.wiring.yaml +137 -0
- package/knowledge/cyberpunk2077/wolvenkit.cli.yaml +167 -0
- package/knowledge/cyberpunk2077/workspot.system.yaml +55 -0
- package/knowledge/cyberpunk2077/world.interactions.yaml +41 -0
- package/knowledge/cyberpunk2077/world.loot-container.yaml +167 -0
- package/knowledge/cyberpunk2077/world.sectors.yaml +233 -0
- package/knowledge/eldenring/formats.binders.yaml +237 -0
- package/knowledge/eldenring/launcher.me3.yaml +230 -0
- package/knowledge/eldenring/launcher.modengine2.yaml +119 -0
- package/knowledge/eldenring/params.paramdef.yaml +149 -0
- package/knowledge/eldenring/params.regulation.yaml +142 -0
- package/knowledge/eldenring/saves.online.yaml +118 -0
- package/knowledge/eldenring/toolchain.cli.yaml +256 -0
- package/knowledge/nivalisnights/modding.runtime.yaml +157 -0
- package/knowledge/skyrimse/archives.bsa.yaml +212 -0
- package/knowledge/skyrimse/install.detection.yaml +41 -0
- package/knowledge/skyrimse/loadorder.files.yaml +242 -0
- package/knowledge/skyrimse/plugins.esl.yaml +189 -0
- package/knowledge/skyrimse/plugins.format.yaml +224 -0
- package/knowledge/skyrimse/skse.runtime.yaml +283 -0
- package/knowledge/skyrimse/toolchain.xedit-spriggit.yaml +336 -0
- package/knowledge/stardewvalley/contentpatcher.format.yaml +338 -0
- package/knowledge/stardewvalley/distribution.channels.yaml +236 -0
- package/knowledge/stardewvalley/game.versions.yaml +202 -0
- package/knowledge/stardewvalley/install.layout.yaml +277 -0
- package/knowledge/stardewvalley/smapi.loader.yaml +284 -0
- package/knowledge/stardewvalley/smapi.logs.yaml +329 -0
- package/knowledge/stardewvalley/smapi.manifest.yaml +293 -0
- package/knowledge/stardewvalley/toolchain.build.yaml +261 -0
- package/knowledge/stardewvalley/wiki.dataformat.yaml +130 -0
- package/knowledge/subnautica2/game.build.yaml +331 -0
- package/knowledge/subnautica2/modding.state.yaml +210 -0
- package/knowledge/subnautica2/ue5.containers.yaml +72 -0
- package/knowledge/subnautica2/ue5.paks.yaml +203 -0
- package/knowledge/subnautica2/ue5.tooling.yaml +175 -0
- package/knowledge/subnautica2/ue5.ue4ss.yaml +203 -0
- package/knowledge/valheim/bepinex.loader.yaml +247 -0
- package/knowledge/valheim/bepinex.plugins.yaml +251 -0
- package/knowledge/valheim/game.versions.yaml +321 -0
- package/knowledge/valheim/install.layout.yaml +216 -0
- package/knowledge/valheim/jotunn.library.yaml +334 -0
- package/knowledge/valheim/thunderstore.packaging.yaml +217 -0
- package/knowledge/valheim/toolchain.build.yaml +111 -0
- package/package.json +29 -0
- package/scaffolds/baldursgate3/new-class-injection.yaml +148 -0
- package/scaffolds/baldursgate3/new-item.yaml +264 -0
- package/scaffolds/baldursgate3/new-mod.yaml +174 -0
- package/scaffolds/baldursgate3/new-passive.yaml +100 -0
- package/scaffolds/baldursgate3/new-project.yaml +118 -0
- package/scaffolds/baldursgate3/new-quest-stub.yaml +159 -0
- package/scaffolds/baldursgate3/new-spell.yaml +102 -0
- package/scaffolds/baldursgate3/new-status.yaml +119 -0
- package/scaffolds/baldursgate3/sequences/subclass-kit.yaml +50 -0
- package/scaffolds/cyberpunk2077/edit-tweak.yaml +70 -0
- package/scaffolds/cyberpunk2077/mesh-export-preset.yaml +170 -0
- package/scaffolds/cyberpunk2077/new-entity-patch.yaml +255 -0
- package/scaffolds/cyberpunk2077/new-garment-refit.yaml +279 -0
- package/scaffolds/cyberpunk2077/new-item-chain.yaml +548 -0
- package/scaffolds/cyberpunk2077/new-localization.yaml +130 -0
- package/scaffolds/cyberpunk2077/new-mod-settings.yaml +133 -0
- package/scaffolds/cyberpunk2077/new-player-replacer.yaml +1003 -0
- package/scaffolds/cyberpunk2077/new-project.yaml +157 -0
- package/scaffolds/cyberpunk2077/new-sector-node.yaml +156 -0
- package/scaffolds/cyberpunk2077/new-tweak.yaml +121 -0
- package/scaffolds/cyberpunk2077/new-vehicle-livery.yaml +148 -0
- package/scaffolds/cyberpunk2077/new-workspot-entity.yaml +177 -0
- package/scaffolds/cyberpunk2077/sequences/iconic-weapon.yaml +72 -0
- package/scaffolds/cyberpunk2077/sequences/quickhack-takeover.yaml +213 -0
- package/scaffolds/stardewvalley/new-cp-patch.yaml +106 -0
- package/scaffolds/stardewvalley/new-csharp-mod.yaml +195 -0
- package/scaffolds/stardewvalley/new-project.yaml +184 -0
- package/scaffolds/stardewvalley/sequences/content-pack.yaml +31 -0
- package/scripts/mw-tool.mjs +184 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# new-csharp-mod (Stardew Valley). Adds a SMAPI C# mod project to an existing Stardew Valley ModWright
|
|
2
|
+
# project: a `src/<name>/` folder holding the `.csproj` the wiki's IDE
|
|
3
|
+
# reference gives (Microsoft.NET.Sdk, net6.0, the Pathoschild.Stardew.ModBuildConfig
|
|
4
|
+
# package reference), the Get Started guide's ModEntry.cs and manifest.json
|
|
5
|
+
# (with the literal version rather than `%ProjectVersion%`, see below), and the
|
|
6
|
+
# project source and dependencies that make the manifest visible to the
|
|
7
|
+
# surface's rules.
|
|
8
|
+
#
|
|
9
|
+
# Two things this scaffold decides for the author:
|
|
10
|
+
# `<EnableModDeploy>false</EnableModDeploy>` and `<EnableModZip>false</EnableModZip>`
|
|
11
|
+
# are set, so the build package does not copy the mod into the game's Mods
|
|
12
|
+
# folder on every build and ModWright's own safety-backed deploy is the one
|
|
13
|
+
# path that writes there. Note the cost: with both off,
|
|
14
|
+
# the package's deploy task returns before it reads the manifest, so it never
|
|
15
|
+
# substitutes `%ProjectVersion%` and never assembles a mod folder — the build
|
|
16
|
+
# output is the DLL alone. The manual checklist carries what that leaves the
|
|
17
|
+
# author to do until a Stardew deploy target exists.
|
|
18
|
+
# Building needs the game installed (the package
|
|
19
|
+
# refuses without `Stardew Valley.dll` and `StardewModdingAPI.dll` beside the
|
|
20
|
+
# game), so the DLL the manifest names is a build output
|
|
21
|
+
# and never sits beside the source manifest; the surface's entrydll-exists
|
|
22
|
+
# rule reports that as an info for a manifest with a .csproj beside it, not
|
|
23
|
+
# as the block a deployed manifest without its DLL gets.
|
|
24
|
+
id: stardewvalley.new-csharp-mod
|
|
25
|
+
game: stardewvalley
|
|
26
|
+
title: New SMAPI C# mod project
|
|
27
|
+
summary: Add a SMAPI C# mod under src/<name>/ — the wiki's .csproj (net6.0, ModBuildConfig, deploy and zip handed to ModWright), the Get Started ModEntry.cs and manifest.json — and register it as a project source with the dotnet and SMAPI dependencies.
|
|
28
|
+
modTypes: [plugin, packaging]
|
|
29
|
+
needs: {}
|
|
30
|
+
inputs:
|
|
31
|
+
- type: string
|
|
32
|
+
name: name
|
|
33
|
+
prompt: Project name (also the assembly, root namespace, folder and EntryDll name; a C# identifier).
|
|
34
|
+
pattern: "^[A-Za-z][A-Za-z0-9_]*$"
|
|
35
|
+
- type: string
|
|
36
|
+
name: uniqueId
|
|
37
|
+
prompt: The manifest UniqueID, YourName.YourModName (letters, numbers, underscores, periods, hyphens; never changed once published).
|
|
38
|
+
pattern: "^[a-zA-Z0-9_.-]+$"
|
|
39
|
+
- type: string
|
|
40
|
+
name: author
|
|
41
|
+
prompt: Author name (no quotes or backslashes; it is written into JSON).
|
|
42
|
+
default: "Unknown"
|
|
43
|
+
pattern: '^[^"\\\x00-\x1f]+$'
|
|
44
|
+
- type: string
|
|
45
|
+
name: version
|
|
46
|
+
prompt: Initial version (major.minor.patch); written to both the .csproj and the manifest, which are bumped together.
|
|
47
|
+
default: "1.0.0"
|
|
48
|
+
pattern: "^(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:\\.(?:0|[1-9][0-9]*))?(?:-(?:[a-zA-Z0-9]+[-.]?)+)?$"
|
|
49
|
+
- type: string
|
|
50
|
+
name: description
|
|
51
|
+
prompt: One or two sentences about the mod (no quotes or backslashes; it is written into JSON).
|
|
52
|
+
default: "One or two sentences about the mod."
|
|
53
|
+
pattern: '^[^"\\\x00-\x1f]+$'
|
|
54
|
+
ids: []
|
|
55
|
+
emits:
|
|
56
|
+
- op: ensure-dir
|
|
57
|
+
path: "src/${input.name}"
|
|
58
|
+
# The .csproj: the IDE reference's example (Sdk, AssemblyName, RootNamespace,
|
|
59
|
+
# Version, TargetFramework net6.0, the package reference) with the package
|
|
60
|
+
# at its current version and the two deploy/zip toggles.
|
|
61
|
+
- op: write-text
|
|
62
|
+
path: "src/${input.name}/${input.name}.csproj"
|
|
63
|
+
body: |
|
|
64
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
|
65
|
+
<PropertyGroup>
|
|
66
|
+
<AssemblyName>${input.name}</AssemblyName>
|
|
67
|
+
<RootNamespace>${input.name}</RootNamespace>
|
|
68
|
+
<Version>${input.version}</Version>
|
|
69
|
+
<TargetFramework>net6.0</TargetFramework>
|
|
70
|
+
<!-- ModWright owns deploy and zip: the package would otherwise copy into Mods/ on every build. -->
|
|
71
|
+
<EnableModDeploy>false</EnableModDeploy>
|
|
72
|
+
<EnableModZip>false</EnableModZip>
|
|
73
|
+
</PropertyGroup>
|
|
74
|
+
|
|
75
|
+
<ItemGroup>
|
|
76
|
+
<PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="4.4.0" />
|
|
77
|
+
</ItemGroup>
|
|
78
|
+
</Project>
|
|
79
|
+
# ModEntry.cs: the Get Started guide's first mod, with the project name as
|
|
80
|
+
# its namespace.
|
|
81
|
+
- op: write-text
|
|
82
|
+
path: "src/${input.name}/ModEntry.cs"
|
|
83
|
+
body: |
|
|
84
|
+
using System;
|
|
85
|
+
using Microsoft.Xna.Framework;
|
|
86
|
+
using StardewModdingAPI;
|
|
87
|
+
using StardewModdingAPI.Events;
|
|
88
|
+
using StardewModdingAPI.Utilities;
|
|
89
|
+
using StardewValley;
|
|
90
|
+
|
|
91
|
+
namespace ${input.name}
|
|
92
|
+
{
|
|
93
|
+
/// <summary>The mod entry point.</summary>
|
|
94
|
+
internal sealed class ModEntry : Mod
|
|
95
|
+
{
|
|
96
|
+
/*********
|
|
97
|
+
** Public methods
|
|
98
|
+
*********/
|
|
99
|
+
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
|
|
100
|
+
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
|
101
|
+
public override void Entry(IModHelper helper)
|
|
102
|
+
{
|
|
103
|
+
helper.Events.Input.ButtonPressed += this.OnButtonPressed;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/*********
|
|
108
|
+
** Private methods
|
|
109
|
+
*********/
|
|
110
|
+
/// <summary>Raised after the player presses a button on the keyboard, controller, or mouse.</summary>
|
|
111
|
+
/// <param name="sender">The event sender.</param>
|
|
112
|
+
/// <param name="e">The event data.</param>
|
|
113
|
+
private void OnButtonPressed(object? sender, ButtonPressedEventArgs e)
|
|
114
|
+
{
|
|
115
|
+
// ignore if player hasn't loaded a save yet
|
|
116
|
+
if (!Context.IsWorldReady)
|
|
117
|
+
return;
|
|
118
|
+
|
|
119
|
+
// print button presses to the console window
|
|
120
|
+
this.Monitor.Log($"{Game1.player.Name} pressed {e.Button}.", LogLevel.Debug);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
# manifest.json: the Get Started guide's manifest, field for field, with
|
|
125
|
+
# the literal version the guide itself uses. The mod-package doc's
|
|
126
|
+
# %ProjectVersion% token is substituted only when the package deploys or
|
|
127
|
+
# zips, and with both toggles off (header comment) it never does, so the
|
|
128
|
+
# token would reach SMAPI unreplaced and the mod would be refused.
|
|
129
|
+
- op: write-text
|
|
130
|
+
path: "src/${input.name}/manifest.json"
|
|
131
|
+
body: |
|
|
132
|
+
{
|
|
133
|
+
"Name": "${input.name}",
|
|
134
|
+
"Author": "${input.author}",
|
|
135
|
+
"Version": "${input.version}",
|
|
136
|
+
"Description": "${input.description}",
|
|
137
|
+
"UniqueID": "${input.uniqueId}",
|
|
138
|
+
"EntryDll": "${input.name}.dll",
|
|
139
|
+
"MinimumApiVersion": "4.0.0",
|
|
140
|
+
"UpdateKeys": []
|
|
141
|
+
}
|
|
142
|
+
- op: patch-project
|
|
143
|
+
add:
|
|
144
|
+
sources:
|
|
145
|
+
- id: "src-${input.name}"
|
|
146
|
+
path: "src/${input.name}"
|
|
147
|
+
kind: source
|
|
148
|
+
dependencies:
|
|
149
|
+
- id: dotnet
|
|
150
|
+
kind: tool
|
|
151
|
+
minVersion: "6.0"
|
|
152
|
+
url: "https://dotnet.microsoft.com/download"
|
|
153
|
+
notes: "`dotnet build -c Release` in src/<name>; the build package needs the game and SMAPI installed to resolve Stardew Valley.dll and StardewModdingAPI.dll."
|
|
154
|
+
- id: smapi
|
|
155
|
+
kind: loader
|
|
156
|
+
minVersion: "4.0.0"
|
|
157
|
+
url: "https://smapi.io"
|
|
158
|
+
notes: "MinimumApiVersion in the manifest; the mod loads only through StardewModdingAPI."
|
|
159
|
+
templates: []
|
|
160
|
+
# The manifest rules the source manifest must pass. entrydll-exists is not
|
|
161
|
+
# listed: for a manifest with a .csproj beside it the rule reports the
|
|
162
|
+
# missing DLL as an info (it is a build output), which is expected here.
|
|
163
|
+
satisfies:
|
|
164
|
+
- stardewvalley.manifest.parses
|
|
165
|
+
- stardewvalley.manifest.required-fields
|
|
166
|
+
- stardewvalley.manifest.entry-or-content-pack
|
|
167
|
+
- stardewvalley.manifest.uniqueid
|
|
168
|
+
- stardewvalley.manifest.version
|
|
169
|
+
- stardewvalley.manifest.minimum-versions
|
|
170
|
+
- stardewvalley.manifest.extra-fields
|
|
171
|
+
manual:
|
|
172
|
+
- title: Build against the installed game
|
|
173
|
+
steps:
|
|
174
|
+
- "With the game and SMAPI installed, run `dotnet build -c Release` in src/<name>; the package finds the game folder itself (or set GamePath, see https://smapi.io/package/custom-game-path)."
|
|
175
|
+
- "The build output is bin/Release/net6.0/<name>.dll and nothing else: with EnableModDeploy and EnableModZip both false the package's deploy task returns before it reads the manifest, so there is no deployed folder, no release zip, and no %ProjectVersion% substitution anywhere."
|
|
176
|
+
expected: "The build succeeds with no 'Any CPU' warning; bin/Release/net6.0 holds <name>.dll (manifest.json is not copied there)."
|
|
177
|
+
- title: Check in game
|
|
178
|
+
steps:
|
|
179
|
+
- "Assemble Mods/<name> by hand, since no deploy target is configured on this game yet: the built <name>.dll plus this project's manifest.json as it is (its Version is the literal the .csproj carries; bump both together). Alternatively set <EnableModZip>true</EnableModZip> for one build and unzip the '<name> <version>.zip' the package then writes into bin/Release/net6.0, which still never writes into Mods/."
|
|
180
|
+
- "Launch StardewModdingAPI.exe and press any key in game: the SMAPI console shows '<player> pressed <button>' at Debug level (the Get Started example's behaviour)."
|
|
181
|
+
expected: "SMAPI's log lists the mod in its 'Loaded N mods' block with no skipped-mods entry."
|
|
182
|
+
claim:
|
|
183
|
+
idSuffix: csharp-mod
|
|
184
|
+
claim: "${input.name} is a SMAPI C# mod project under src/${input.name} (UniqueID ${input.uniqueId}, net6.0, ModBuildConfig 4.4.0 with deploy and zip handed to ModWright)."
|
|
185
|
+
testRows:
|
|
186
|
+
- gate: S-0
|
|
187
|
+
title: "Mod builds and loads"
|
|
188
|
+
expected: "dotnet build succeeds against the installed game; SMAPI's log lists the mod with no skipped-mods entry and the button-press line appears at Debug."
|
|
189
|
+
manual: true
|
|
190
|
+
probeKinds: []
|
|
191
|
+
evidence:
|
|
192
|
+
- "stardewvalley.toolchain.build.modbuildconfig-package"
|
|
193
|
+
- "stardewvalley.toolchain.build.deploy-and-zip-properties"
|
|
194
|
+
- "stardewvalley.toolchain.build.requires-the-game-installed"
|
|
195
|
+
- "stardewvalley.smapi.manifest.project-version-token"
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# new-project (Stardew Valley). A `new-content-pack`, carried under the `new-project` id because the
|
|
2
|
+
# `scaffold` tool bootstraps a project only for an id ending in
|
|
3
|
+
# `.new-project` (src/server.ts), and a Content Patcher pack is the first
|
|
4
|
+
# project on this game: it needs no toolchain, no compiler and no game
|
|
5
|
+
# to author. Writes the pack the Content Patcher author
|
|
6
|
+
# guide's quick-start describes — a `[CP] <name>` folder with
|
|
7
|
+
# `manifest.json`, `content.json` and an `assets/` folder — plus the
|
|
8
|
+
# ModWright project around it. tests/authored.yaml and ledger/claims.yaml
|
|
9
|
+
# come from the engine's own per-apply steps, not an emit here.
|
|
10
|
+
#
|
|
11
|
+
# The pack is not empty: Content Patcher rejects a pack whose `Changes`
|
|
12
|
+
# and `CustomLocations` are both empty ("content pack must specify the
|
|
13
|
+
# Changes or CustomLocations fields"), so the quick-
|
|
14
|
+
# start's `"Changes": [ // your changes will go here ]` would be refused
|
|
15
|
+
# at load. The one starter patch is the wiki's own Mail data example
|
|
16
|
+
# shape: an EditData on `Data/mail` adding a `{{ModId}}_`-prefixed letter,
|
|
17
|
+
# which the 1.6 unique-string-ID convention asks for and which reaches no
|
|
18
|
+
# player until something sends it ("This letter will have to be sent in a
|
|
19
|
+
# separate patch", Modding:Mail data). Replacing it is the first manual
|
|
20
|
+
# step.
|
|
21
|
+
id: stardewvalley.new-project
|
|
22
|
+
game: stardewvalley
|
|
23
|
+
title: New Stardew Valley content pack project
|
|
24
|
+
summary: Scaffold a fresh ModWright project holding one Content Patcher content pack — modwright.json (schemaVersion 2), the [CP] <name> folder with manifest.json, content.json (Format 2.9.0, one starter Data/mail patch) and assets/, .gitignore, and ledger/decisions.yaml.
|
|
25
|
+
modTypes: [content-pack, packaging]
|
|
26
|
+
needs: {}
|
|
27
|
+
inputs:
|
|
28
|
+
- type: string
|
|
29
|
+
name: name
|
|
30
|
+
prompt: Mod name (the pack folder is "[CP] <name>", the author guide's convention).
|
|
31
|
+
pattern: "^[A-Za-z][A-Za-z0-9_-]*$"
|
|
32
|
+
- type: string
|
|
33
|
+
name: uniqueId
|
|
34
|
+
prompt: The manifest UniqueID, YourName.YourModName (letters, numbers, underscores, periods, hyphens; never changed once published).
|
|
35
|
+
pattern: "^[a-zA-Z0-9_.-]+$"
|
|
36
|
+
# author and description are the only free-text inputs that land inside a
|
|
37
|
+
# JSON string literal in a hand-written `write-text` body (every other one
|
|
38
|
+
# is already pattern-guarded). A `"` or `\` in either would emit a
|
|
39
|
+
# manifest.json that is not JSON at all — SMAPI then reports the mod as
|
|
40
|
+
# "parsing its manifest failed" and loads nothing — so they are refused up
|
|
41
|
+
# front rather than written and reported afterwards. Control characters go
|
|
42
|
+
# with them: a raw tab or newline inside a JSON string is invalid too.
|
|
43
|
+
- type: string
|
|
44
|
+
name: author
|
|
45
|
+
prompt: Author name (no double quotes or backslashes — it is written into manifest.json as-is).
|
|
46
|
+
default: "Unknown"
|
|
47
|
+
pattern: '^[^"\\\x00-\x1f]+$'
|
|
48
|
+
- type: string
|
|
49
|
+
name: version
|
|
50
|
+
prompt: Initial version (major.minor.patch, as SMAPI parses it).
|
|
51
|
+
default: "1.0.0"
|
|
52
|
+
pattern: "^(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:\\.(?:0|[1-9][0-9]*))?(?:-(?:[a-zA-Z0-9]+[-.]?)+)?$"
|
|
53
|
+
- type: string
|
|
54
|
+
name: description
|
|
55
|
+
prompt: One or two sentences about the mod (the manifest Description; no double quotes or backslashes).
|
|
56
|
+
default: "One or two sentences about the mod."
|
|
57
|
+
pattern: '^[^"\\\x00-\x1f]+$'
|
|
58
|
+
ids: []
|
|
59
|
+
emits:
|
|
60
|
+
- op: ensure-dir
|
|
61
|
+
path: "[CP] ${input.name}/assets"
|
|
62
|
+
- op: write-text
|
|
63
|
+
path: ".gitignore"
|
|
64
|
+
ifExists: skip
|
|
65
|
+
# The same shape as the other two new-project scaffolds: suppressions.json
|
|
66
|
+
# and templates/manifest.json stay tracked so a reviewer reads them in a
|
|
67
|
+
# clean checkout, and the build manifest a later build step writes is
|
|
68
|
+
# ignored wherever outDir points.
|
|
69
|
+
body: |
|
|
70
|
+
.modwright/*
|
|
71
|
+
!.modwright/suppressions.json
|
|
72
|
+
!.modwright/templates/
|
|
73
|
+
.modwright/templates/*
|
|
74
|
+
!.modwright/templates/manifest.json
|
|
75
|
+
build/
|
|
76
|
+
.modwright-build-manifest.json
|
|
77
|
+
- op: write-text
|
|
78
|
+
path: "ledger/decisions.yaml"
|
|
79
|
+
body: |
|
|
80
|
+
decisions: []
|
|
81
|
+
# The project: one source of kind "content-pack" covering the pack
|
|
82
|
+
# folder, so every manifest and content rule sees the two files (the
|
|
83
|
+
# lesson cyberpunk2077/new-project.yaml records: a file outside every
|
|
84
|
+
# declared source is invisible to file-scoped rules). No build and no
|
|
85
|
+
# deploy yet: a Stardew deploy target is not built, and a content pack has
|
|
86
|
+
# nothing to compile — the pack folder is what gets copied into Mods/.
|
|
87
|
+
- op: write-text
|
|
88
|
+
path: "modwright.json"
|
|
89
|
+
body: |
|
|
90
|
+
{
|
|
91
|
+
"schemaVersion": 2,
|
|
92
|
+
"name": "${input.name}",
|
|
93
|
+
"game": "stardewvalley",
|
|
94
|
+
"version": "${input.version}",
|
|
95
|
+
"authors": ["${input.author}"],
|
|
96
|
+
"sources": [
|
|
97
|
+
{ "id": "pack", "path": "[CP] ${input.name}", "kind": "content-pack" }
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
# manifest.json: the author guide's quick-start manifest, field for
|
|
101
|
+
# field (Name, Author, Version, Description, UniqueID, UpdateKeys,
|
|
102
|
+
# ContentPackFor). UpdateKeys stays empty until the mod has a page; the
|
|
103
|
+
# guide's own comment on that line points at the update-checks wiki page.
|
|
104
|
+
- op: write-text
|
|
105
|
+
path: "[CP] ${input.name}/manifest.json"
|
|
106
|
+
body: |
|
|
107
|
+
{
|
|
108
|
+
"Name": "${input.name}",
|
|
109
|
+
"Author": "${input.author}",
|
|
110
|
+
"Version": "${input.version}",
|
|
111
|
+
"Description": "${input.description}",
|
|
112
|
+
"UniqueID": "${input.uniqueId}",
|
|
113
|
+
"UpdateKeys": [],
|
|
114
|
+
"ContentPackFor": {
|
|
115
|
+
"UniqueID": "Pathoschild.ContentPatcher"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
# content.json: the quick-start's Format, the schema line the
|
|
119
|
+
# troubleshooting guide recommends for editors, and the one starter patch
|
|
120
|
+
# (see the header comment). `^` is a line break and `@` the player's name
|
|
121
|
+
# in mail text; `[#]` ends the body and names the letter.
|
|
122
|
+
- op: write-text
|
|
123
|
+
path: "[CP] ${input.name}/content.json"
|
|
124
|
+
body: |
|
|
125
|
+
{
|
|
126
|
+
"$schema": "https://smapi.io/schemas/content-patcher.json",
|
|
127
|
+
"Format": "2.9.0",
|
|
128
|
+
"Changes": [
|
|
129
|
+
{
|
|
130
|
+
"LogName": "Welcome letter",
|
|
131
|
+
"Action": "EditData",
|
|
132
|
+
"Target": "Data/mail",
|
|
133
|
+
"Entries": {
|
|
134
|
+
"{{ModId}}_Welcome": "Hi @,^^This letter was added by the ${input.name} content pack. Replace this patch with your first real change.^^ -${input.author}[#]Welcome from ${input.name}"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
templates: []
|
|
140
|
+
# Every rule below runs against the two files this scaffold writes and must
|
|
141
|
+
# come back with zero findings: the manifest family and the content family. manifest.update-keys
|
|
142
|
+
# is deliberately not listed — an empty UpdateKeys is its documented info,
|
|
143
|
+
# not a failure, and a scaffolded mod has no page yet.
|
|
144
|
+
satisfies:
|
|
145
|
+
- stardewvalley.manifest.parses
|
|
146
|
+
- stardewvalley.manifest.required-fields
|
|
147
|
+
- stardewvalley.manifest.entry-or-content-pack
|
|
148
|
+
- stardewvalley.manifest.uniqueid
|
|
149
|
+
- stardewvalley.manifest.version
|
|
150
|
+
- stardewvalley.manifest.extra-fields
|
|
151
|
+
- stardewvalley.content.parses
|
|
152
|
+
- stardewvalley.content.format
|
|
153
|
+
- stardewvalley.content.changes-present
|
|
154
|
+
- stardewvalley.content.patch-action
|
|
155
|
+
- stardewvalley.content.patch-target
|
|
156
|
+
- stardewvalley.content.patch-fields
|
|
157
|
+
- stardewvalley.content.fromfile-exists
|
|
158
|
+
- stardewvalley.content.patch-enabled
|
|
159
|
+
- stardewvalley.content.when-tokens
|
|
160
|
+
manual:
|
|
161
|
+
- title: Replace the starter patch
|
|
162
|
+
steps:
|
|
163
|
+
- "Edit [CP] <name>/content.json: replace the Welcome letter patch with the first real change (the author guide's first example is a Load of Portraits/Abigail from assets/abigail.png), or run the new-cp-patch scaffold to append one."
|
|
164
|
+
- "Put any file a FromFile names under assets/; validate reports a FromFile that does not exist as a block."
|
|
165
|
+
- "Check both files at https://smapi.io/json (Manifest and Content Patcher formats) before shipping."
|
|
166
|
+
expected: "validate is clean; with the game installed, SMAPI's log lists the mod and Content Patcher's `patch summary` shows every patch loaded."
|
|
167
|
+
- title: Install and check in game
|
|
168
|
+
steps:
|
|
169
|
+
- "Copy the [CP] <name> folder into the game's Mods/ folder (deploy is not configured on this game yet) and launch StardewModdingAPI.exe."
|
|
170
|
+
- "In the SMAPI console run `patch summary` and find the pack's patches in the loaded | conditions | applied table."
|
|
171
|
+
expected: "The pack appears in the log's own 'Loaded N content packs:' list (not the 'Loaded N mods' list, which is C# mods only) under its manifest Name, followed by '| for Content Patcher', and nowhere in the 'Skipped mods' list."
|
|
172
|
+
claim:
|
|
173
|
+
idSuffix: scaffolded
|
|
174
|
+
claim: "${input.name} is scaffolded as a ModWright project holding the Content Patcher pack [CP] ${input.name} (UniqueID ${input.uniqueId}, Format 2.9.0) with one starter Data/mail patch."
|
|
175
|
+
testRows:
|
|
176
|
+
- gate: S-0
|
|
177
|
+
title: "Pack loads under SMAPI"
|
|
178
|
+
expected: "SMAPI's log lists the pack by its manifest Name in the 'Loaded N content packs:' list, '| for Content Patcher', with no 'Skipped mods' entry, and `patch summary` shows the Welcome letter patch as loaded."
|
|
179
|
+
manual: true
|
|
180
|
+
probeKinds: []
|
|
181
|
+
evidence:
|
|
182
|
+
- "stardewvalley.contentpatcher.format.what-a-pack-is"
|
|
183
|
+
- "stardewvalley.contentpatcher.format.whole-pack-rejection-messages"
|
|
184
|
+
- "stardewvalley.game.versions.unique-string-ids-convention"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# content-pack (Stardew Valley) — the smallest sequence: a Content Patcher
|
|
2
|
+
# pack and its first real patch. A C# mod cannot compile without the game,
|
|
3
|
+
# so the first Stardew project is always a content pack.
|
|
4
|
+
id: stardewvalley.content-pack
|
|
5
|
+
game: stardewvalley
|
|
6
|
+
title: Content Patcher pack with one patch
|
|
7
|
+
summary: A Content Patcher pack (manifest, content.json, assets/) and its first Load or EditImage patch over an asset the modder supplies.
|
|
8
|
+
modType: content-pack
|
|
9
|
+
inputs:
|
|
10
|
+
- name: modName
|
|
11
|
+
prompt: "Mod name; the pack folder is \"[CP] <name>\"."
|
|
12
|
+
- name: uniqueId
|
|
13
|
+
prompt: "The manifest UniqueID, YourName.YourModName (never changed once published)."
|
|
14
|
+
steps:
|
|
15
|
+
- id: project
|
|
16
|
+
scaffold: stardewvalley.new-project
|
|
17
|
+
title: The pack and its project file
|
|
18
|
+
skipIf: project-exists
|
|
19
|
+
inputs:
|
|
20
|
+
name: "${sequence.modName}"
|
|
21
|
+
uniqueId: "${sequence.uniqueId}"
|
|
22
|
+
- id: patch
|
|
23
|
+
scaffold: stardewvalley.new-cp-patch
|
|
24
|
+
title: The first patch over a game asset
|
|
25
|
+
inputs:
|
|
26
|
+
folder: "[CP] ${sequence.modName}"
|
|
27
|
+
assets:
|
|
28
|
+
- name: file
|
|
29
|
+
prompt: "The file the patch loads or edits with (a PNG for an image target, a data file otherwise), placed under the pack's assets/ folder. Path relative to the pack folder, e.g. assets/portrait.png."
|
|
30
|
+
inputs: [fromFile]
|
|
31
|
+
evidence: []
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Call any ModWright tool from a shell, through a fresh server process, with
|
|
4
|
+
* no MCP client in the way.
|
|
5
|
+
*
|
|
6
|
+
* npm run tool -- list [--schemas]
|
|
7
|
+
* npm run tool -- call <tool> [key=value ...] [--json '<object>'] [--args-file <file>] [--out <file>]
|
|
8
|
+
* npm run tool -- prompts
|
|
9
|
+
* npm run tool -- prompt <name> [path=<project>] [--out <file>]
|
|
10
|
+
*
|
|
11
|
+
* Why: an MCP client's tool list is fixed at its handshake, so a server
|
|
12
|
+
* rebuilt after the session started is invisible to it. Every invocation
|
|
13
|
+
* here spawns the server that is on disk right now, so a rebuilt ModWright is usable from the next shell command,
|
|
14
|
+
* whatever the surrounding client believes its tools are.
|
|
15
|
+
*
|
|
16
|
+
* Argument values given as key=value are parsed as JSON when they parse
|
|
17
|
+
* (true, 3, ["a"], {"k":1}) and taken as strings otherwise, so
|
|
18
|
+
* `mode=apply` and `force=true` both do what they look like. `--json` and
|
|
19
|
+
* `--args-file` take a whole object; later sources override earlier ones,
|
|
20
|
+
* in the order file, --json, key=value. `--out` writes the result text to a
|
|
21
|
+
* file instead of stdout. MODWRIGHT_* environment variables are forwarded.
|
|
22
|
+
* Long tools (build_index) are given a generous request timeout; there is
|
|
23
|
+
* no 60 s ceiling here. Exit code 1 when the tool reports an error.
|
|
24
|
+
*/
|
|
25
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
26
|
+
import { StdioClientTransport, getDefaultEnvironment } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
27
|
+
import { promises as fs } from "node:fs";
|
|
28
|
+
import * as path from "node:path";
|
|
29
|
+
import { fileURLToPath } from "node:url";
|
|
30
|
+
|
|
31
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
32
|
+
const REQUEST_TIMEOUT_MS = 6 * 60 * 60 * 1000;
|
|
33
|
+
|
|
34
|
+
const argv = process.argv.slice(2);
|
|
35
|
+
const command = argv.shift();
|
|
36
|
+
if (command !== "list" && command !== "call" && command !== "prompts" && command !== "prompt") {
|
|
37
|
+
usage();
|
|
38
|
+
process.exit(command === undefined || command === "--help" || command === "-h" ? 0 : 2);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function usage() {
|
|
42
|
+
process.stdout.write(
|
|
43
|
+
[
|
|
44
|
+
"usage:",
|
|
45
|
+
" mw-tool list [--schemas]",
|
|
46
|
+
" mw-tool call <tool> [key=value ...] [--json '<object>'] [--args-file <file>] [--out <file>]",
|
|
47
|
+
" mw-tool prompts list the workflow prompts the server serves",
|
|
48
|
+
" mw-tool prompt <name> [path=<dir>] render one workflow prompt for a project",
|
|
49
|
+
"",
|
|
50
|
+
"Every call spawns a fresh ModWright server from dist/, so it always reflects the current build.",
|
|
51
|
+
"",
|
|
52
|
+
].join("\n"),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function takeFlag(flag) {
|
|
57
|
+
const i = argv.indexOf(flag);
|
|
58
|
+
if (i === -1) return undefined;
|
|
59
|
+
const value = argv[i + 1];
|
|
60
|
+
argv.splice(i, 2);
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function takeSwitch(flag) {
|
|
65
|
+
const i = argv.indexOf(flag);
|
|
66
|
+
if (i === -1) return false;
|
|
67
|
+
argv.splice(i, 1);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const entry = process.env.MODWRIGHT_ENTRY ?? path.join(repoRoot, "dist", "index.js");
|
|
72
|
+
const env = { ...getDefaultEnvironment(), MODWRIGHT_NO_HOT_RELOAD: "1" };
|
|
73
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
74
|
+
if (key.startsWith("MODWRIGHT_") && value !== undefined) env[key] = value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const client = new Client({ name: "modwright-tool-cli", version: "1.0.0" });
|
|
78
|
+
const transport = new StdioClientTransport({ command: process.execPath, args: [entry], env, stderr: "inherit" });
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
await client.connect(transport);
|
|
82
|
+
if (command === "list") {
|
|
83
|
+
const withSchemas = takeSwitch("--schemas");
|
|
84
|
+
const { tools } = await client.listTools();
|
|
85
|
+
tools.sort((a, b) => a.name.localeCompare(b.name));
|
|
86
|
+
if (withSchemas) {
|
|
87
|
+
process.stdout.write(`${JSON.stringify(tools, null, 2)}\n`);
|
|
88
|
+
} else {
|
|
89
|
+
for (const t of tools) {
|
|
90
|
+
const params = Object.keys(t.inputSchema?.properties ?? {}).join(", ");
|
|
91
|
+
process.stdout.write(`${t.name}${params ? ` (${params})` : ""}\n`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} else if (command === "prompts") {
|
|
95
|
+
const { prompts } = await client.listPrompts();
|
|
96
|
+
for (const p of prompts) process.stdout.write(`${p.name} ${p.description ?? ""}\n`);
|
|
97
|
+
} else if (command === "prompt") {
|
|
98
|
+
const outFile = takeFlag("--out");
|
|
99
|
+
const name = argv.shift();
|
|
100
|
+
if (!name) {
|
|
101
|
+
usage();
|
|
102
|
+
process.exit(2);
|
|
103
|
+
}
|
|
104
|
+
const promptArgs = {};
|
|
105
|
+
for (const pair of argv) {
|
|
106
|
+
const eq = pair.indexOf("=");
|
|
107
|
+
if (eq <= 0) {
|
|
108
|
+
process.stderr.write(`mw-tool: expected key=value, got "${pair}"\n`);
|
|
109
|
+
process.exit(2);
|
|
110
|
+
}
|
|
111
|
+
promptArgs[pair.slice(0, eq)] = pair.slice(eq + 1);
|
|
112
|
+
}
|
|
113
|
+
const result = await client.getPrompt({ name, arguments: promptArgs });
|
|
114
|
+
const text = (result.messages ?? [])
|
|
115
|
+
.map((m) => (m.content?.type === "text" ? m.content.text : `[${m.content?.type} content]`))
|
|
116
|
+
.join("\n\n");
|
|
117
|
+
if (outFile) {
|
|
118
|
+
await fs.writeFile(outFile, `${text}\n`, "utf8");
|
|
119
|
+
process.stderr.write(`mw-tool: wrote ${outFile}\n`);
|
|
120
|
+
} else {
|
|
121
|
+
process.stdout.write(`${text}\n`);
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
const outFile = takeFlag("--out");
|
|
125
|
+
const argsFile = takeFlag("--args-file");
|
|
126
|
+
const jsonArgs = takeFlag("--json");
|
|
127
|
+
const tool = argv.shift();
|
|
128
|
+
if (!tool) {
|
|
129
|
+
usage();
|
|
130
|
+
process.exit(2);
|
|
131
|
+
}
|
|
132
|
+
let args = {};
|
|
133
|
+
if (argsFile) Object.assign(args, JSON.parse(await fs.readFile(argsFile, "utf8")));
|
|
134
|
+
if (jsonArgs) Object.assign(args, JSON.parse(jsonArgs));
|
|
135
|
+
for (const pair of argv) {
|
|
136
|
+
const eq = pair.indexOf("=");
|
|
137
|
+
if (eq <= 0) {
|
|
138
|
+
process.stderr.write(`mw-tool: expected key=value, got "${pair}"\n`);
|
|
139
|
+
process.exit(2);
|
|
140
|
+
}
|
|
141
|
+
const key = pair.slice(0, eq);
|
|
142
|
+
const raw = pair.slice(eq + 1);
|
|
143
|
+
args[key] = parseValue(raw);
|
|
144
|
+
}
|
|
145
|
+
const result = await client.callTool({ name: tool, arguments: args }, undefined, { timeout: REQUEST_TIMEOUT_MS, resetTimeoutOnProgress: true });
|
|
146
|
+
const text = (result.content ?? [])
|
|
147
|
+
.map((c) => (c.type === "text" ? c.text : `[${c.type} content]`))
|
|
148
|
+
.join("\n");
|
|
149
|
+
const pretty = prettify(text);
|
|
150
|
+
if (outFile) {
|
|
151
|
+
await fs.writeFile(outFile, `${pretty}\n`, "utf8");
|
|
152
|
+
process.stderr.write(`mw-tool: wrote ${outFile}\n`);
|
|
153
|
+
} else {
|
|
154
|
+
process.stdout.write(`${pretty}\n`);
|
|
155
|
+
}
|
|
156
|
+
if (result.isError) process.exitCode = 1;
|
|
157
|
+
}
|
|
158
|
+
} catch (error) {
|
|
159
|
+
process.stderr.write(`mw-tool: ${error?.message ?? error}\n`);
|
|
160
|
+
process.exitCode = 1;
|
|
161
|
+
} finally {
|
|
162
|
+
await client.close().catch(() => {});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function parseValue(raw) {
|
|
166
|
+
if (raw === "") return "";
|
|
167
|
+
const first = raw[0];
|
|
168
|
+
if (first === "{" || first === "[" || first === '"' || raw === "true" || raw === "false" || raw === "null" || /^-?\d+(\.\d+)?$/.test(raw)) {
|
|
169
|
+
try {
|
|
170
|
+
return JSON.parse(raw);
|
|
171
|
+
} catch {
|
|
172
|
+
return raw;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return raw;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function prettify(text) {
|
|
179
|
+
try {
|
|
180
|
+
return JSON.stringify(JSON.parse(text), null, 2);
|
|
181
|
+
} catch {
|
|
182
|
+
return text;
|
|
183
|
+
}
|
|
184
|
+
}
|