Achievehaus.Plugin 0.3.7-preview.1

This is a prerelease version of Achievehaus.Plugin.
dotnet add package Achievehaus.Plugin --version 0.3.7-preview.1
                    
NuGet\Install-Package Achievehaus.Plugin -Version 0.3.7-preview.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Achievehaus.Plugin" Version="0.3.7-preview.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Achievehaus.Plugin" Version="0.3.7-preview.1" />
                    
Directory.Packages.props
<PackageReference Include="Achievehaus.Plugin" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Achievehaus.Plugin --version 0.3.7-preview.1
                    
#r "nuget: Achievehaus.Plugin, 0.3.7-preview.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Achievehaus.Plugin@0.3.7-preview.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Achievehaus.Plugin&version=0.3.7-preview.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Achievehaus.Plugin&version=0.3.7-preview.1&prerelease
                    
Install as a Cake Tool

Achievehaus.Plugin

Write Achievehaus plugins in C#.

One class is the plugin: mark it [Plugin], derive it from PluginBase, and override the methods of the roles it plays:

role override source.json declares it with
detector Check(ClipEvents events) a method without a template
screen Seen(Sighting sighting, ClipEvents events) watches (its method names the moments)
action Outcome Run(string action, Clip clip) actions
resolver Discovery Discover(IReadOnlyList<string> followed) a resolver
page PageData View(string page, Span? scope), PageData Act(string page, string action) pages
using Achievehaus;

[Plugin]
public sealed class Unlocks : PluginBase
{
    LogTail log = null!;

    public override void Start(Settings settings, Context context) =>
        log = LogTail.Open(settings.GetString("log_path"));

    public override void Check(ClipEvents events)
    {
        foreach (var line in log.NewLines())
            if (line.StartsWith("Achievement unlocked: "))
                events.Emit(new ClipEvent().Var("name", line[22..]));
    }
}

Start a project with the plugin kit:

achievehaus-plugin new my-plugin --lang csharp
cd my-plugin && achievehaus-plugin run

Roles. source.json says which roles the source plays, and the app runs each in an instance of its own: a new object of your class, started once with Start (context.Role says which). A role you do not override answers not-implemented. The build says so first: no [Plugin] class, two of them, or one the app cannot make (abstract, generic, no public constructor taking nothing) is a compile error (AH0001--AH0003); one that overrides no role is a warning (AH0004); a role source.json declares that the class does not override is an error (AH0005), and one the class overrides that source.json does not declare a warning (AH0006). The instances share nothing at run time but the settings and the folders: what one role works out for another goes in State.

  • Screen. A Sighting has the watch's id, when it was seen, a match's Score and Exemplar, the OCR's Lines (each with its box as fractions of the region) and the Crop's pixels. Read.Lines("killer", "victim").Drop("KILL FEED") (or Read.Regions().Region(...)) turns the lines into vars: Vars(lines), Map(lines). Its events are live; it has no network. A C# screen plugin does not load yet: .NET's start needs ~52M fuel and the role's configure gets 50M (#346).
  • Action. A Clip has its title, source, kind, vars (when this plugin saved it), game, At, Duration, MomentOffset and Files -- the video first, Video -- as read handles: Read(offset, len) (4 MiB at most) or OpenRead(), a seekable Stream an upload sends as Request.BodyStream. Answer Outcome.Done(link), Outcome.Trim(from, to) or Outcome.Skipped; throw for a failure. Secrets.Set(token) keeps the plugin's own sign-in (a secret need with "writable": true), Set("") signs out.
  • Resolver. new Discovery(installs), .Add(install), .Following(dir) (a second library: the app grants it and calls again with it in followed), .Client("MyLauncher") (the launcher's own program, never the game).
  • Page. new PageData().Vars("tonight", new Vars().Var("matches", 3)).Rows("recent", rows); Act is the page again by default. Pages.Changed("matches"), from any role, has the app ask View again while the page is on screen.

What every role may ask the app:

Http.Get, Http.Post, Http.Send requests over wasi:http, to the hosts source.json grants ({ "wasi": "http", "authority": [...] }); Http.GetJson is null for any failure
Status.Report, Status.Clear, Notes.Show status notes: what the plugin is waiting for, beside the session it is about; Because, Steps, Brings, Expected, Setting say its detail
State.ReadJson, WriteJson, ReadText, WriteText, Path the plugin's state folder (/state), 8 MiB, every role's; a write goes to {name}.partial and is renamed into place
Registry.ReadString, ReadU32, Subkeys the Windows registry, read only, under the keys source.json grants
LogTail, Seen, Every following a log, keeping only what is new, doing something less often

System.Net.Http does not reach the app under componentize-dotnet, which is why Http is the SDK's own: one request at a time, blocking until the whole answer is in, a body's content-length sent for it. JSON in State goes through JsonNode, or a JsonTypeInfo<T> from a JsonSerializerContext: the component is trimmed, and System.Text.Json's reflection is off in it. What the plugin writes to Console.Out or Console.Error is its log.

The package brings componentize-dotnet, the app's world and the generator that finds the [Plugin] class; a plugin project holds no WIT and no generated code, and the component keeps nothing of the SDK it does not call (no reflection: the generator settles which class and which roles when it compiles, and an export of a role not played compiles to not-implemented alone). A resolver is about 3 MiB, a detector about 4, a plugin playing every role about 7.

Testing. Everything but the app's imports runs natively, so a plugin's own tests call its methods: new Sighting("feed").WithLines("Ana", "Bo"), ClipFile.FromBytes(...) in a new Clip(...), new Settings(json). Outside a component the registry finds nothing, notes go nowhere, HTTP throws, State is $ACHIEVEHAUS_STATE_DIR (else achievehaus-state in the temporary folder), and Pages.TakeChanged() and Secrets.TakeSet() hand back what was said.

Platforms. The component is built by NativeAOT-LLVM, which runs on Windows and Linux. On macOS the plugin compiles and type-checks, and the build then stops with an explanation: NativeAOT-LLVM has no macOS build yet (dotnet/runtimelab#2119). The component itself runs on every platform the app does.

Its tests. dotnet test Achievehaus.Plugin.Tests (from sdk/csharp) runs everything that works outside a component, on any OS, and the generator over sample plugins; .github/workflows/plugin-kit.yml builds every C# template and examples/ (a plugin per role the templates do not cover, and one playing every role) into a component and runs it in the app's sandbox.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.7-preview.1 47 11/8/2026
0.3.6-preview.1 64 11/5/2026
0.3.5-preview.1 63 11/4/2026
0.3.4-preview.1 55 11/4/2026
0.3.3-preview.1 68 10/31/2026
0.3.2-preview.1 74 10/30/2026
0.3.1-preview.1 63 10/30/2026
0.3.0-preview.1 59 10/30/2026