diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 4b1b5ab..6799076 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -338,6 +338,10 @@ jobs: # requires_plugins = ["Kits", "ZoneManager"] is already a JSON array. # One line, quoted strings only; anything else fails the check below. REQUIRES="$(grep -m1 -E '^requires_plugins[[:space:]]*=' overlay.toml | sed -E 's/^[^=]*=[[:space:]]*//')" + # The RunicNPC API the bridge's npc.* commands need (runicnpc stage 4). 0 when + # absent, which a bundle reads as "carries no RunicNPC". + RUNICNPC_API="$(grep -m1 -E '^runicnpc_api[[:space:]]*=' overlay.toml | sed -E 's/[^0-9]//g')" + RUNICNPC_API="${RUNICNPC_API:-0}" [ -n "$PROTOCOL" ] || { echo "::error::could not read protocol from overlay.toml"; exit 1; } [ -n "$MIN_OXIDE" ] || { echo "::error::could not read min_oxide_version from overlay.toml"; exit 1; } [ -n "$MIN_CARBON" ] || { echo "::error::could not read min_carbon_version from overlay.toml"; exit 1; } @@ -354,6 +358,7 @@ jobs: --arg min_oxide "${MIN_OXIDE}" \ --arg min_carbon "${MIN_CARBON}" \ --argjson requires "${REQUIRES}" \ + --argjson runicnpc "${RUNICNPC_API}" \ --argjson files "${FILES}" \ '{ component: $component, @@ -364,6 +369,7 @@ jobs: min_oxide_version: $min_oxide, min_carbon_version: $min_carbon, requires_plugins: $requires, + runicnpc_api: $runicnpc, files: $files }' > "${STAGE}/manifest.json" echo "----- manifest.json -----" diff --git a/overlay.toml b/overlay.toml index 3093524..5f22132 100644 --- a/overlay.toml +++ b/overlay.toml @@ -77,3 +77,15 @@ min_carbon_version = "2.0.259" # asked of a server without it is refused with a reason, and chat is the default. # BetterChat is optional in the same way — titles and group styles wait for it. requires_plugins = ["Kits", "ZoneManager"] + +# ── The RunicNPC API the bridge needs ─────────────────────────────────────── +# +# RunicNPC (docs/runicnpc/PLAN.md stage 4): the bridge's npc.* commands call +# RunicNPC's API and need at least this version of it. It MUST equal +# `RunicNpcApiNeeded` in RunicGateway.cs; `node scripts/checkPlugin.js` holds the +# two equal. The release copies it into manifest.json, and the installer's +# bundle carries the latest RunicNPC release that answers at least it (D224). +# +# RunicNPC is optional to the bridge until its stage 9: without it every npc.* +# command answers `runicnpc-missing`, and events place Rust's own scientists. +runicnpc_api = 3 diff --git a/scripts/checkPlugin.js b/scripts/checkPlugin.js index d7ac002..bf4e078 100644 --- a/scripts/checkPlugin.js +++ b/scripts/checkPlugin.js @@ -198,6 +198,14 @@ function check(source, toml) { // 5. The two declaration sites this repository owns must agree. const inCode = /ProtocolVersion\s*=\s*(\d+)\s*;/.exec(source) + // runicnpc stage 4: the RunicNPC API the bridge needs, declared twice like the protocol. + const npcToml = /^\s*runicnpc_api\s*=\s*(\d+)\s*$/m.exec(toml) + const npcCode = /const\s+int\s+RunicNpcApiNeeded\s*=\s*(\d+)\s*;/.exec(source) + if (npcCode && !npcToml) problems.push('the plugin needs a RunicNPC API (RunicNpcApiNeeded) and overlay.toml declares no runicnpc_api') + if (npcCode && npcToml && npcCode[1] !== npcToml[1]) { + problems.push(`the plugin needs RunicNPC API ${npcCode[1]} and overlay.toml declares runicnpc_api = ${npcToml[1]}. The bundle picks a RunicNPC by the second, so they must agree.`) + } + const inToml = /^\s*protocol\s*=\s*(\d+)\s*$/m.exec(toml) if (!inCode) problems.push('could not read ProtocolVersion from the plugin source')