From 6e45d802ecee62b82ef127c408bb84853f05b551 Mon Sep 17 00:00:00 2001 From: Marino Rottier Date: Tue, 28 Apr 2026 21:25:57 +0200 Subject: [PATCH] Automatically publish plugin types to NPM (#26283) * add workflow and package.json for publishing plugin TypeScript types * move scripting-related files to scripting folder * add support for trusted publishers * fix path to scripting readme * rename scripting README.md back to scripting.md * support tagged/dev releases * add workflow for development versions * Update package.json website * change dependencies in publish-plugin-types * add timestamp to dev plugin versions * note ScriptEngine.h grep dependency from CI * use gh-describe to track release version for dev plugin types --- .github/labeler.yml | 2 +- .github/workflows/publish-plugin-types.yml | 79 ++++++++++++++++++++++ CMakeLists.txt | 4 +- distribution/{ => scripting}/openrct2.d.ts | 0 distribution/scripting/package.json | 24 +++++++ distribution/{ => scripting}/scripting.md | 20 ++++++ distribution/windows/install.nsi | 4 +- readme.md | 2 +- scripts/build-portable | 4 +- src/openrct2/ride/CarEntry.h | 2 +- src/openrct2/scripting/IconNames.hpp | 2 +- src/openrct2/scripting/ScriptEngine.h | 1 + 12 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/publish-plugin-types.yml rename distribution/{ => scripting}/openrct2.d.ts (100%) create mode 100644 distribution/scripting/package.json rename distribution/{ => scripting}/scripting.md (98%) diff --git a/.github/labeler.yml b/.github/labeler.yml index cd4be7e588..ab86758517 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -46,7 +46,7 @@ 'plug-in': - changed-files: - any-glob-to-any-file: - - 'distribution/openrct2.d.ts' + - 'distribution/scripting/openrct2.d.ts' - 'src/openrct2/scripting/*' - 'src/openrct2-ui/scripting/*' diff --git a/.github/workflows/publish-plugin-types.yml b/.github/workflows/publish-plugin-types.yml new file mode 100644 index 0000000000..ea2c1e6e99 --- /dev/null +++ b/.github/workflows/publish-plugin-types.yml @@ -0,0 +1,79 @@ +name: Publish plugin API types to npm +on: + push: + tags: + - 'v*' + branches: + - develop + paths: + - 'distribution/scripting/openrct2.d.ts' + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g. 0.4.32). Leave empty to use the tag version.' + required: false + +jobs: + publish: + name: Publish @openrct2/types + runs-on: ubuntu-slim + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + sparse-checkout: | + distribution/scripting + src/openrct2/scripting/ScriptEngine.h + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 24 + registry-url: https://registry.npmjs.org + + - name: Get latest release tag + if: github.ref == 'refs/heads/develop' + id: describe + uses: proudust/gh-describe@v2 + with: + match: 'v*' + + - name: Determine version + id: version + run: | + if [[ -n "${{ github.event.inputs.version }}" ]]; then + VERSION="${{ github.event.inputs.version }}" + elif [[ "$GITHUB_REF" == refs/tags/v* ]]; then + VERSION="${GITHUB_REF#refs/tags/v}" + elif [[ "$GITHUB_REF" == refs/heads/develop ]]; then + BASE_VERSION="${{ steps.describe.outputs.tag }}" + BASE_VERSION="${BASE_VERSION#v}" + API_VERSION=$(grep -oP 'kPluginApiVersion\s*=\s*\K[0-9]+' src/openrct2/scripting/ScriptEngine.h) + TIMESTAMP=$(date -u +%Y%m%d%H%M%S) + VERSION="${BASE_VERSION}-dev.${API_VERSION}.${TIMESTAMP}" + else + echo "::error::No version could be determined. Run on a tag or provide a version input." + exit 1 + fi + echo "version=$VERSION" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + if [[ "$VERSION" == *-* ]]; then + echo "tag=dev" >> "$GITHUB_OUTPUT" + else + echo "tag=latest" >> "$GITHUB_OUTPUT" + fi + + - name: Prepare README for npm + working-directory: distribution/scripting + run: cp scripting.md README.md + + - name: Set package version + working-directory: distribution/scripting + run: npm version "${{ steps.version.outputs.version }}" --no-git-tag-version + + - name: Publish + working-directory: distribution/scripting + run: npm publish --access public --tag "${{ steps.version.outputs.tag }}" diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c80503e1f..3369eb1459 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -435,8 +435,8 @@ if (NOT MACOS_BUNDLE OR (MACOS_BUNDLE AND WITH_TESTS)) list(APPEND DOC_FILES "${ROOT_DIR}/contributors.md" "${ROOT_DIR}/PRIVACY.md" "${ROOT_DIR}/licence.txt" - "${ROOT_DIR}/distribution/scripting.md" - "${ROOT_DIR}/distribution/openrct2.d.ts") + "${ROOT_DIR}/distribution/scripting/scripting.md" + "${ROOT_DIR}/distribution/scripting/openrct2.d.ts") if (DOWNLOAD_TITLE_SEQUENCES) # Checks if this version of the title sequences are already installed, updates if necessary diff --git a/distribution/openrct2.d.ts b/distribution/scripting/openrct2.d.ts similarity index 100% rename from distribution/openrct2.d.ts rename to distribution/scripting/openrct2.d.ts diff --git a/distribution/scripting/package.json b/distribution/scripting/package.json new file mode 100644 index 0000000000..2808287d82 --- /dev/null +++ b/distribution/scripting/package.json @@ -0,0 +1,24 @@ +{ + "name": "@openrct2/types", + "description": "TypeScript type definitions for the OpenRCT2 Plugin API", + "license": "GPL-3.0", + "repository": { + "type": "git", + "url": "https://github.com/OpenRCT2/OpenRCT2.git", + "directory": "distribution/scripting" + }, + "homepage": "https://openrct2.io/", + "keywords": [ + "openrct2", + "types", + "typescript", + "plugin", + "modding", + "scripting" + ], + "types": "openrct2.d.ts", + "files": [ + "openrct2.d.ts", + "README.md" + ] +} diff --git a/distribution/scripting.md b/distribution/scripting/scripting.md similarity index 98% rename from distribution/scripting.md rename to distribution/scripting/scripting.md index 87ce44b38a..99d3b94914 100644 --- a/distribution/scripting.md +++ b/distribution/scripting/scripting.md @@ -21,6 +21,26 @@ Official references for writing plugins are: * Our collection of sample scripts: [OpenRCT2/plugin-samples](https://github.com/OpenRCT2/plugin-samples) * A TypeScript plugin comprised of multiple sources: [IntelOrca/OpenRCT2-ParkManager](https://github.com/IntelOrca/OpenRCT2-ParkManager) +### TypeScript types + +The Plugin API type definitions are available on npm as [`@openrct2/types`](https://www.npmjs.com/package/@openrct2/types). This gives you autocomplete and type checking in your editor. + +``` +npm install @openrct2/types --save-dev +``` + +Then add it to your `tsconfig.json`: + +```json +{ + "compilerOptions": { + "types": ["@openrct2/types"] + } +} +``` + +The package version follows OpenRCT2 releases (e.g. `0.4.32` matches OpenRCT2 `v0.4.32`). + Start by copying this template script into a new file in your `plugin` directory: ```js function main() { diff --git a/distribution/windows/install.nsi b/distribution/windows/install.nsi index bd4af31fd4..e367c15cad 100644 --- a/distribution/windows/install.nsi +++ b/distribution/windows/install.nsi @@ -215,10 +215,10 @@ Section "!OpenRCT2" Section1 File ..\..\PRIVACY.md Push "$INSTDIR\PRIVACY.md" Call unix2dos - File ..\scripting.md + File ..\scripting\scripting.md Push "$INSTDIR\scripting.md" Call unix2dos - File ..\openrct2.d.ts + File ..\scripting\openrct2.d.ts Push "$INSTDIR\openrct2.d.ts" Call unix2dos diff --git a/readme.md b/readme.md index 40ce3a37d2..2b83cfab4a 100644 --- a/readme.md +++ b/readme.md @@ -156,7 +156,7 @@ See [PRIVACY.md](PRIVACY.md) for more information. - [OpenRCT2 subreddit](https://www.reddit.com/r/openrct2/) - OpenRCT2 plug-ins - [Plug-in directory (unofficial)](https://openrct2plugins.org) - - [Plug-in development documentation](https://github.com/OpenRCT2/OpenRCT2/blob/develop/distribution/scripting.md) + - [Plug-in development documentation](https://github.com/OpenRCT2/OpenRCT2/blob/develop/distribution/scripting/scripting.md) ## Similar Projects diff --git a/scripts/build-portable b/scripts/build-portable index 61cda98659..ec45361828 100755 --- a/scripts/build-portable +++ b/scripts/build-portable @@ -26,8 +26,8 @@ if [[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" ]]; then ../licence.txt \ ../distribution/changelog.txt \ ../distribution/readme.txt \ - ../distribution/scripting.md \ - ../distribution/openrct2.d.ts + ../distribution/scripting/scripting.md \ + ../distribution/scripting/openrct2.d.ts destination=$(cygpath -w $(readlink -f $destination)) printf '\033[0;32m%s\033[0m\n' "${destination} created successfully" diff --git a/src/openrct2/ride/CarEntry.h b/src/openrct2/ride/CarEntry.h index 9063311c1e..e306b20344 100644 --- a/src/openrct2/ride/CarEntry.h +++ b/src/openrct2/ride/CarEntry.h @@ -110,7 +110,7 @@ using CarEntryFlags = FlagHolder; /* * When adding a sprite group, add multiplier to SpriteGroupMultiplier in RideObject.cpp and add sprite group data to cable - * lift hill vehicle in RideData.cpp and update the SpriteGroups interface in distribution/openrct2.d.ts + * lift hill vehicle in RideData.cpp and update the SpriteGroups interface in distribution/scripting/openrct2.d.ts */ enum class SpriteGroupType : uint8_t { diff --git a/src/openrct2/scripting/IconNames.hpp b/src/openrct2/scripting/IconNames.hpp index 0e59e23822..7a16419261 100644 --- a/src/openrct2/scripting/IconNames.hpp +++ b/src/openrct2/scripting/IconNames.hpp @@ -17,7 +17,7 @@ namespace OpenRCT2::Scripting { - // When adding to this map, also add to IconName in openrct2.d.ts + // When adding to this map, also add to IconName in distribution/scripting/openrct2.d.ts static EnumMap SpriteLookupTable = { // G1 Icons diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index 6156e35b01..fb7f5aaec9 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -42,6 +42,7 @@ namespace OpenRCT2 namespace OpenRCT2::Scripting { + // Grepped from CI (.github/workflows/publish-plugin-types.yml); keep the format `kPluginApiVersion = N`. static constexpr int32_t kPluginApiVersion = 113; // Versions marking breaking changes.