From a9c6938f0ed21add5007ece984f1948d5d30d3d3 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 26 Sep 2026 16:00:00 +0200 Subject: [PATCH 1/8] Build, test and release on the club Gitea A Forgejo workflow builds and tests every push and pull request on the club's docker runner. A v* tag also assembles the plugin zip, checks it with OpenAC's own plugin checker, and publishes a Gitea release with the zip, its checksum and plugin.json. The checker refused the manifest: both permission notes were over the launcher's 120-character limit. They are shorter now. Co-Authored-By: Claude Opus 5.5 --- .forgejo/workflows/ci.yml | 103 ++++++++++++++++++++++++ src/OpenAC.MosswartMassacre/plugin.json | 4 +- tools/build-release-zip.sh | 63 +++++++++++++++ 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 .forgejo/workflows/ci.yml create mode 100755 tools/build-release-zip.sh diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml new file mode 100644 index 0000000..4685e1d --- /dev/null +++ b/.forgejo/workflows/ci.yml @@ -0,0 +1,103 @@ +name: CI + +on: + push: + branches: [main] + tags: ['v*'] + pull_request: + branches: [main] + +env: + # The OpenAC release whose AcDream.Plugin.Abstractions package this plugin + # builds against. PluginApiPackageVersion in Directory.Build.props has to + # name the same version. + OPENAC_API_RELEASE_TAG: v0.1.19 + OPENAC_API_VERSION: 0.1.19 + +jobs: + build-and-test: + runs-on: docker + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + + - name: Install the pinned .NET SDK + uses: https://github.com/actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Fetch the plugin contract package + run: | + set -euo pipefail + mkdir -p packages-local + curl -fsSL -o "packages-local/AcDream.Plugin.Abstractions.${OPENAC_API_VERSION}.nupkg" \ + "https://github.com/eriknihlen/OpenAC/releases/download/${OPENAC_API_RELEASE_TAG}/AcDream.Plugin.Abstractions.${OPENAC_API_VERSION}.nupkg" + + - name: Build + run: dotnet build OpenAC.MosswartMassacre.slnx -c Release --nologo + + - name: Test + run: dotnet test OpenAC.MosswartMassacre.slnx -c Release --no-build --nologo + + release: + # Tag pushes only, once the build and tests are green. + if: startsWith(github.ref, 'refs/tags/v') + needs: [build-and-test] + runs-on: docker + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + + - name: Install the pinned .NET SDK + uses: https://github.com/actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Fetch the plugin contract package + run: | + set -euo pipefail + mkdir -p packages-local + curl -fsSL -o "packages-local/AcDream.Plugin.Abstractions.${OPENAC_API_VERSION}.nupkg" \ + "https://github.com/eriknihlen/OpenAC/releases/download/${OPENAC_API_RELEASE_TAG}/AcDream.Plugin.Abstractions.${OPENAC_API_VERSION}.nupkg" + + - name: Build + run: dotnet build OpenAC.MosswartMassacre.slnx -c Release --nologo + + - name: Assemble the release assets + run: | + set -euo pipefail + bash tools/build-release-zip.sh Release artifacts | tee build-zip.out + cat build-zip.out >> "$GITHUB_ENV" + + # The tag is the version the release is known by; the manifest's version + # is what an install reads. They have to agree. + - name: The tag has to name the manifest's version + run: | + set -euo pipefail + if [ "${GITHUB_REF_NAME}" != "v${version}" ]; then + echo "Tag '${GITHUB_REF_NAME}' does not name the manifest version (v${version})." >&2 + exit 1 + fi + + # acdream-plugincheck is the OpenAC launcher's own install code, built + # from the same OpenAC release the contract package comes from. + - name: Check the zip with the launcher's own install code + run: | + set -euo pipefail + git clone --quiet --depth 1 --branch "$OPENAC_API_RELEASE_TAG" https://github.com/eriknihlen/OpenAC.git .openac + dotnet run --project .openac/src/AcDream.PluginCheck -c Release -- "$zip" + + - name: Publish the release + env: + TOKEN: ${{ secrets.FORGEJO_TOKEN }} + run: | + set -euo pipefail + api="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" + body=$(python3 -c 'import json,sys; print(json.dumps({"tag_name": sys.argv[1], "name": "Mosswart Massacre " + sys.argv[1]}))' "$GITHUB_REF_NAME") + id=$(curl -fsS -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ + -d "$body" "$api/releases" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])') + for file in artifacts/plugin.json artifacts/*.zip artifacts/*.zip.sha256; do + curl -fsS -X POST -H "Authorization: token $TOKEN" \ + -F "attachment=@${file}" "$api/releases/${id}/assets?name=$(basename "$file")" > /dev/null + echo "uploaded $(basename "$file")" + done diff --git a/src/OpenAC.MosswartMassacre/plugin.json b/src/OpenAC.MosswartMassacre/plugin.json index 44fc070..47694d1 100644 --- a/src/OpenAC.MosswartMassacre/plugin.json +++ b/src/OpenAC.MosswartMassacre/plugin.json @@ -9,7 +9,7 @@ "minHostVersion": "0.1.19", "capabilitiesVersion": 1, "capabilities": [ - { "name": "network", "note": "Streams telemetry, vitals, chat, inventory and stats to the Mosswart Overlord backend, and receives shared vitals and chat-box commands from it." }, - { "name": "chat", "note": "Reads chat for kills, rares and combat stats, forwards it to the backend, and runs commands typed into the Overlord chat box." } + { "name": "network", "note": "Streams stats, vitals, chat and inventory to Mosswart Overlord, and receives shared vitals and commands from it." }, + { "name": "chat", "note": "Reads chat for kills, rares and combat stats, forwards it to Overlord, and runs commands sent from its chat box." } ] } diff --git a/tools/build-release-zip.sh b/tools/build-release-zip.sh new file mode 100755 index 0000000..9e37d58 --- /dev/null +++ b/tools/build-release-zip.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Assembles the plugin release zip and its .sha256 sidecar from a Release build. +# +# The layout is the one the OpenAC launcher's installer accepts: +# - plugin.json and the entry DLL sit at the zip root; +# - only these extensions: .dll .pdb .json .xml .txt .md .png .jpg .jpeg .ttf .otf; +# - no runtimes/ folder, and no AcDream assembly beside the plugin's own; +# - the plugin.json published as its own release asset is the same file as the +# zip's copy; +# - the sidecar is `sha256sum`'s line: the hash, two spaces, the zip's name. +# Asset names are -.zip and -.zip.sha256. +set -euo pipefail + +configuration="${1:-Release}" +output="${2:-artifacts}" +repo="$(cd "$(dirname "$0")/.." && pwd)" +build="$repo/src/OpenAC.MosswartMassacre/bin/$configuration/net10.0" + +[ -d "$build" ] || { echo "No build output at $build. Build the solution first." >&2; exit 1; } + +read_field() { + python3 -c 'import json,sys; print(json.load(open(sys.argv[1], encoding="utf-8-sig"))[sys.argv[2]])' "$build/plugin.json" "$1" +} +id="$(read_field id)" +version="$(read_field version)" +entry="$(read_field entryDll)" +stem="${entry%.dll}" + +staging="$(mktemp -d)" +trap 'rm -rf "$staging"' EXIT + +for name in plugin.json "$entry" "$stem.pdb" "$stem.deps.json" Newtonsoft.Json.dll; do + [ -f "$build/$name" ] || { echo "The build output has no '$name'." >&2; exit 1; } + cp "$build/$name" "$staging/" +done +cp "$build"/mosswartmassacre-*.xml "$staging/" + +for file in "$staging"/*; do + name="$(basename "$file")" + case "${name,,}" in + *.dll|*.pdb|*.json|*.xml|*.txt|*.md|*.png|*.jpg|*.jpeg|*.ttf|*.otf) ;; + *) echo "'$name' has an extension the launcher refuses." >&2; exit 1 ;; + esac + if [[ "$name" == AcDream.*.dll ]]; then + echo "'$name' is a client assembly beside the plugin." >&2; exit 1 + fi +done + +mkdir -p "$repo/$output" +zip="$repo/$output/$id-$version.zip" +rm -f "$zip" +python3 - "$staging" "$zip" <<'PY' +import os, sys, zipfile +src, dst = sys.argv[1], sys.argv[2] +with zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as z: + for name in sorted(os.listdir(src)): + z.write(os.path.join(src, name), name) +PY +(cd "$repo/$output" && sha256sum "$id-$version.zip" > "$id-$version.zip.sha256") +cp "$build/plugin.json" "$repo/$output/plugin.json" + +echo "zip=$zip" +echo "version=$version" From 4b90aa8348fd06a6ca22f0402c38909a4422b597 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 26 Sep 2026 16:01:38 +0200 Subject: [PATCH 2/8] Temporary: post CI failure output to the PR --- .forgejo/workflows/ci.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 4685e1d..9f9c4b7 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -34,10 +34,24 @@ jobs: "https://github.com/eriknihlen/OpenAC/releases/download/${OPENAC_API_RELEASE_TAG}/AcDream.Plugin.Abstractions.${OPENAC_API_VERSION}.nupkg" - name: Build - run: dotnet build OpenAC.MosswartMassacre.slnx -c Release --nologo + run: dotnet build OpenAC.MosswartMassacre.slnx -c Release --nologo 2>&1 | tee -a ci.log; exit ${PIPESTATUS[0]} + shell: bash - name: Test - run: dotnet test OpenAC.MosswartMassacre.slnx -c Release --no-build --nologo + run: dotnet test OpenAC.MosswartMassacre.slnx -c Release --no-build --nologo 2>&1 | tee -a ci.log; exit ${PIPESTATUS[0]} + shell: bash + + - name: Temporary - post the failure output + if: failure() + env: + TOKEN: ${{ secrets.FORGEJO_TOKEN }} + run: | + (dotnet --info 2>&1 | head -20; echo ----; tail -c 6000 ci.log 2>/dev/null) > diag.txt || true + python3 -c 'import json,sys; print(json.dumps({"body": "CI failure output: +``` +" + open("diag.txt", errors="replace").read() + " +```"}))' > diag.json + curl -fsS -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" -d @diag.json "${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/issues/2/comments" > /dev/null release: # Tag pushes only, once the build and tests are green. From 84155c0d18bad03cdd106ea2df1ffd7dec2ac832 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 26 Sep 2026 16:01:46 +0200 Subject: [PATCH 3/8] Temporary: fix the failure-report step --- .forgejo/workflows/ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 9f9c4b7..85caa24 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -47,10 +47,7 @@ jobs: TOKEN: ${{ secrets.FORGEJO_TOKEN }} run: | (dotnet --info 2>&1 | head -20; echo ----; tail -c 6000 ci.log 2>/dev/null) > diag.txt || true - python3 -c 'import json,sys; print(json.dumps({"body": "CI failure output: -``` -" + open("diag.txt", errors="replace").read() + " -```"}))' > diag.json + python3 -c 'import json; t=open("diag.txt", errors="replace").read(); n=chr(10); f=chr(96)*3; print(json.dumps({"body": "CI failure output:"+n+f+n+t+n+f}))' > diag.json curl -fsS -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" -d @diag.json "${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/issues/2/comments" > /dev/null release: From 32878d825e7813897427d1577044b18b2ddd1e86 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 26 Sep 2026 16:03:22 +0200 Subject: [PATCH 4/8] Test server: a dropped connection closes on every platform On Linux, aborting the server-side WebSocket left the TCP connection open, so the client never saw the drop and the reconnect test timed out on the Gitea runner. Ending the response closes it everywhere, as a real server's drop does. Co-Authored-By: Claude Opus 5.5 --- .../Backend/TestSocketServer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/OpenAC.MosswartMassacre.Tests/Backend/TestSocketServer.cs b/tests/OpenAC.MosswartMassacre.Tests/Backend/TestSocketServer.cs index 6ac58d6..7ee2790 100644 --- a/tests/OpenAC.MosswartMassacre.Tests/Backend/TestSocketServer.cs +++ b/tests/OpenAC.MosswartMassacre.Tests/Backend/TestSocketServer.cs @@ -17,6 +17,7 @@ internal sealed class TestSocketServer : IDisposable private readonly CancellationTokenSource _cts = new(); private readonly Task _accept; private WebSocket? _current; + private HttpListenerContext? _currentContext; public TestSocketServer() { @@ -53,7 +54,12 @@ internal sealed class TestSocketServer : IDisposable { WebSocket socket = await WaitForSocketAsync(); socket.Abort(); + // Aborting the socket alone leaves the TCP connection open on some + // platforms' listeners, so the client never sees the drop; ending the + // response closes the connection everywhere, as a real server's drop does. + _currentContext?.Response.Abort(); _current = null; + _currentContext = null; } public string NextFrame(int timeoutMs = 5000) @@ -111,6 +117,7 @@ internal sealed class TestSocketServer : IDisposable Secrets.Enqueue(context.Request.Headers["X-Plugin-Secret"]); HttpListenerWebSocketContext ws = await context.AcceptWebSocketAsync(null); _current = ws.WebSocket; + _currentContext = context; _ = Task.Run(() => ReadLoopAsync(ws.WebSocket)); } } From ac2e89c0578bbaf25784343f100cbf67bbe20f9b Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 26 Sep 2026 16:04:16 +0200 Subject: [PATCH 5/8] Remove the temporary failure-report step Co-Authored-By: Claude Opus 5.5 --- .forgejo/workflows/ci.yml | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 85caa24..4685e1d 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -34,21 +34,10 @@ jobs: "https://github.com/eriknihlen/OpenAC/releases/download/${OPENAC_API_RELEASE_TAG}/AcDream.Plugin.Abstractions.${OPENAC_API_VERSION}.nupkg" - name: Build - run: dotnet build OpenAC.MosswartMassacre.slnx -c Release --nologo 2>&1 | tee -a ci.log; exit ${PIPESTATUS[0]} - shell: bash + run: dotnet build OpenAC.MosswartMassacre.slnx -c Release --nologo - name: Test - run: dotnet test OpenAC.MosswartMassacre.slnx -c Release --no-build --nologo 2>&1 | tee -a ci.log; exit ${PIPESTATUS[0]} - shell: bash - - - name: Temporary - post the failure output - if: failure() - env: - TOKEN: ${{ secrets.FORGEJO_TOKEN }} - run: | - (dotnet --info 2>&1 | head -20; echo ----; tail -c 6000 ci.log 2>/dev/null) > diag.txt || true - python3 -c 'import json; t=open("diag.txt", errors="replace").read(); n=chr(10); f=chr(96)*3; print(json.dumps({"body": "CI failure output:"+n+f+n+t+n+f}))' > diag.json - curl -fsS -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" -d @diag.json "${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/issues/2/comments" > /dev/null + run: dotnet test OpenAC.MosswartMassacre.slnx -c Release --no-build --nologo release: # Tag pushes only, once the build and tests are green. From 55dc989f85dcb8c4b7d0bf157813e6ed0167d3dc Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 27 Sep 2026 20:47:52 +0200 Subject: [PATCH 6/8] Release local peer subscriptions when combat sharing stops --- .forgejo/workflows/ci.yml | 4 ++-- Directory.Build.props | 2 +- README.md | 6 ++++++ .../Sharing/VitalSharing.cs | 5 +++++ src/OpenAC.MosswartMassacre/plugin.json | 2 +- .../Fakes/FakeNetwork.cs | 10 ++++++++++ .../Sharing/VitalSharingTests.cs | 15 +++++++++++++++ 7 files changed, 40 insertions(+), 4 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 4685e1d..0937187 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -11,8 +11,8 @@ env: # The OpenAC release whose AcDream.Plugin.Abstractions package this plugin # builds against. PluginApiPackageVersion in Directory.Build.props has to # name the same version. - OPENAC_API_RELEASE_TAG: v0.1.19 - OPENAC_API_VERSION: 0.1.19 + OPENAC_API_RELEASE_TAG: v0.1.21 + OPENAC_API_VERSION: 0.1.21 jobs: build-and-test: diff --git a/Directory.Build.props b/Directory.Build.props index 1d2b472..ff76fdd 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -15,7 +15,7 @@ - 0.1.19 + 0.1.21 false diff --git a/README.md b/README.md index 70d0c4a..81c4e1f 100644 --- a/README.md +++ b/README.md @@ -56,3 +56,9 @@ dotnet run --project tools/FrameRecorder -- record 18765 frames.jsonl /mm ws url ws://localhost:18765/websocket/ dotnet run --project tools/FrameRecorder -- compare decal.jsonl port.jsonl ``` + +## Local peer subscriptions + +Requires OpenAC 0.1.21. Combat vital sharing acquires a local state/cast subscription only while enabled, and releases it on disable, logout or unload. Dashboard vitals still stream every five seconds directly from character state without enabling local peer communication. Existing remote WebSocket frames and timing are unchanged. + +Before the new contract release exists, pack AcDream.Plugin.Abstractions 0.1.21 from the matching OpenAC checkout and copy its nupkg into packages-local before restore/build. CI downloads that release, so publish the OpenAC contract before dependent plugin releases. diff --git a/src/OpenAC.MosswartMassacre/Sharing/VitalSharing.cs b/src/OpenAC.MosswartMassacre/Sharing/VitalSharing.cs index 6baf92b..de4dd99 100644 --- a/src/OpenAC.MosswartMassacre/Sharing/VitalSharing.cs +++ b/src/OpenAC.MosswartMassacre/Sharing/VitalSharing.cs @@ -56,6 +56,7 @@ internal sealed class VitalSharing : IMmFeature, IBackendConnectionListener, ISh private readonly MmContext _context; private readonly PeerTable _peers = new(); private IDisposable? _timer; + private IDisposable? _peerSubscription; private int _lastHealth = -1, _lastMaxHealth = -1; private int _lastStamina = -1, _lastMaxStamina = -1; @@ -103,6 +104,8 @@ internal sealed class VitalSharing : IMmFeature, IBackendConnectionListener, ISh if (IsActive) return; IsActive = true; + _peerSubscription = _context.Automation.Network.Subscribe( + PluginPeerCapabilities.ClientState | PluginPeerCapabilities.Casts); ResetOutgoingState(); _timer = _context.Scheduler.Every(TickInterval, OnTick); _context.Send(new @@ -121,6 +124,8 @@ internal sealed class VitalSharing : IMmFeature, IBackendConnectionListener, ISh if (!IsActive) return; IsActive = false; + _peerSubscription?.Dispose(); + _peerSubscription = null; _timer?.Dispose(); _timer = null; _context.Send(new diff --git a/src/OpenAC.MosswartMassacre/plugin.json b/src/OpenAC.MosswartMassacre/plugin.json index 47694d1..4cbbf4d 100644 --- a/src/OpenAC.MosswartMassacre/plugin.json +++ b/src/OpenAC.MosswartMassacre/plugin.json @@ -6,7 +6,7 @@ "apiVersion": 1, "kinds": ["Gameplay"], "hosts": ["Graphical", "Headless"], - "minHostVersion": "0.1.19", + "minHostVersion": "0.1.21", "capabilitiesVersion": 1, "capabilities": [ { "name": "network", "note": "Streams stats, vitals, chat and inventory to Mosswart Overlord, and receives shared vitals and commands from it." }, diff --git a/tests/OpenAC.MosswartMassacre.Tests/Fakes/FakeNetwork.cs b/tests/OpenAC.MosswartMassacre.Tests/Fakes/FakeNetwork.cs index e3a7c88..132537f 100644 --- a/tests/OpenAC.MosswartMassacre.Tests/Fakes/FakeNetwork.cs +++ b/tests/OpenAC.MosswartMassacre.Tests/Fakes/FakeNetwork.cs @@ -8,6 +8,16 @@ namespace OpenAC.MosswartMassacre.Tests.Fakes; /// public sealed class FakeNetwork : INetworkAutomation { + public bool SupportsSubscriptions => true; + public List Requests { get; } = []; + public int ActiveLeases { get; private set; } + public IDisposable Subscribe(PluginPeerCapabilities capabilities) + { Requests.Add(capabilities); ActiveLeases++; return new Lease(this); } + private sealed class Lease(FakeNetwork owner) : IDisposable + { + private bool _disposed; + public void Dispose() { if (_disposed) return; _disposed = true; owner.ActiveLeases--; } + } public bool IsAvailable { get; set; } = true; public List ImportedClients { get; } = []; diff --git a/tests/OpenAC.MosswartMassacre.Tests/Sharing/VitalSharingTests.cs b/tests/OpenAC.MosswartMassacre.Tests/Sharing/VitalSharingTests.cs index 10ac642..61f31a0 100644 --- a/tests/OpenAC.MosswartMassacre.Tests/Sharing/VitalSharingTests.cs +++ b/tests/OpenAC.MosswartMassacre.Tests/Sharing/VitalSharingTests.cs @@ -42,6 +42,21 @@ public sealed class VitalSharingTests private static VitalSharing Feature(PluginHarness harness) => harness.Feature(); + [Fact] + public void Local_peer_subscription_exists_only_while_combat_sharing_is_enabled() + { + using var harness = Sharing(); + var network = harness.Host.Automation.Network; + Assert.Empty(network.Requests); + Feature(harness).Start(); + Feature(harness).Start(); + Assert.Equal(1, network.ActiveLeases); + Assert.Equal(PluginPeerCapabilities.ClientState | PluginPeerCapabilities.Casts, Assert.Single(network.Requests)); + Feature(harness).OnLogoff(); + Feature(harness).Dispose(); + Assert.Equal(0, network.ActiveLeases); + } + [Fact] public void Subscribe_on_start_carries_the_player_id_and_tags() { From f3731051200818be3c7a6def49d551759fad8c1d Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 27 Sep 2026 22:07:42 +0200 Subject: [PATCH 7/8] Release subscription-based combat sharing as 0.1.1 --- Directory.Build.props | 2 +- README.md | 8 ++++---- src/OpenAC.MosswartMassacre/plugin.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ff76fdd..068ba5a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -10,7 +10,7 @@ true - 0.1.0 + 0.1.1 - 0.1.21 + 0.1.22 false diff --git a/README.md b/README.md index c060839..9015d56 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,12 @@ byte-for-byte what the DECAL plugin sent and accepted; the golden tests under ## Building The plugin contract is `AcDream.Plugin.Abstractions` of the version named in -`Directory.Build.props` (`PluginApiPackageVersion`), currently 0.1.21, the -OpenAC 0.1.21 release. Put that release's package in `packages-local/`; an -OpenAC client from 0.1.21 on loads the plugin. +`Directory.Build.props` (`PluginApiPackageVersion`), currently 0.1.22, the +OpenAC 0.1.22 release. Put that release's package in `packages-local/`; an +OpenAC client from 0.1.22 on loads the plugin. ``` -gh release download v0.1.21 --repo eriknihlen/OpenAC -p "AcDream.Plugin.Abstractions.0.1.21.nupkg" -D packages-local +gh release download v0.1.22 --repo eriknihlen/OpenAC -p "AcDream.Plugin.Abstractions.0.1.22.nupkg" -D packages-local dotnet build OpenAC.MosswartMassacre.slnx dotnet test OpenAC.MosswartMassacre.slnx ``` @@ -59,6 +59,6 @@ dotnet run --project tools/FrameRecorder -- compare decal.jsonl port.jsonl ## Local peer subscriptions -Requires OpenAC 0.1.21. Combat vital sharing acquires a local state/cast subscription only while enabled, and releases it on disable, logout or unload. Dashboard vitals still stream every five seconds directly from character state without enabling local peer communication. Existing remote WebSocket frames and timing are unchanged. +Requires OpenAC 0.1.22. Combat vital sharing acquires a local state/cast subscription only while enabled, and releases it on disable, logout or unload. Dashboard vitals still stream every five seconds directly from character state without enabling local peer communication. Existing remote WebSocket frames and timing are unchanged. -Before the new contract release exists, pack AcDream.Plugin.Abstractions 0.1.21 from the matching OpenAC checkout and copy its nupkg into packages-local before restore/build. CI downloads that release, so publish the OpenAC contract before dependent plugin releases. +Before the new contract release exists, pack AcDream.Plugin.Abstractions 0.1.22 from the matching OpenAC checkout and copy its nupkg into packages-local before restore/build. CI downloads that release, so publish the OpenAC contract before dependent plugin releases. diff --git a/src/OpenAC.MosswartMassacre/plugin.json b/src/OpenAC.MosswartMassacre/plugin.json index bd7223e..8f0b2e4 100644 --- a/src/OpenAC.MosswartMassacre/plugin.json +++ b/src/OpenAC.MosswartMassacre/plugin.json @@ -6,7 +6,7 @@ "apiVersion": 1, "kinds": ["Gameplay"], "hosts": ["Graphical", "Headless"], - "minHostVersion": "0.1.21", + "minHostVersion": "0.1.22", "capabilitiesVersion": 1, "capabilities": [ { "name": "network", "note": "Streams stats, vitals, chat and inventory to Mosswart Overlord, and receives shared vitals and commands from it." },