-
Notifications
You must be signed in to change notification settings - Fork 2
01.01.99. Web Plug‐Ins ‐ SDK
Plug-in SDK is a package that you can use to develop your own plug-in for PKHeX.Web
- Create a .NET project
# create a folder for your plugin
mkdir PlugIn.Demo
# change the directory
cd PlugIn.Demo
# create a razor class lib
# (can also be a classlib if your plug-in doesn't need to render UI components)
dotnet new razorclasslib
# open VS Code
code .
- Configure your project file
Edit your project file (./PlugIn.Demo.csproj
in this demo) adding the following lines:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<!--add the following lines before the closing of /PropertyGroup-->
<DebugType>portable</DebugType>
<EmbedAllSources>true</EmbedAllSources>
<PublishSingleFile>true</PublishSingleFile>
<Version>1.0.0</Version>
<!--until here-->
</PropertyGroup>
</Project>
The rest you can leave as it is
- Add the SDK to your project
You can see the latest version here.
dotnet add package PKHeX.Web.Plugins
If all is good, you should a log stream that resembles the following:
Determining projects to restore...
info : Adding PackageReference for package 'PKHeX.Web.Plugins' into project '...'.
info : GET https://api.nuget.org/v3/registration5-gz-semver2/pkhex.web.plugins/index.json
... sequence omitted
info : PackageReference for package 'PKHeX.Web.Plugins' version '0.6.2' added to file './PlugIn.Demo.csproj'.
info : Writing assets file to disk. Path: /Users/Arley_SilvaDePadua/repos/personal/plugin-demo/obj/project.assets.json
log : Restored /Users/Arley_SilvaDePadua/repos/personal/PlugIn.Demo/PlugIn.Demo.csproj (in 1.74 sec).
- Add your plug-in manifest
Add a new class having the name you like. I usually have the name of the plug-in, in this case: PlugInDemo.cs
and make it implement the abstract class Settings
like the following:
public class PlugInDemo : Settings
{
public PlugInDemo() : base(Manifest)
{
// optionally define settings that may be useful to allow user to control
// this["Some boolean setting"] = new SettingValue.BooleanValue(true);
// this["Some integer setting"] = new SettingValue.IntegerValue(1);
// this["Some string setting"] = new SettingValue.StringValue("a value");
// this["Some file setting"] = new SettingValue.FileValue([], string.Empty);
// optionally define the features you want to leave enabled by default
// if none is set, everything will be disabled by default
// EnabledByDefault<DemoAction>();
}
private static readonly PlugInManifest Manifest = new PlugInManifest(
"Demo Plug-In",
"Description of the plug-in");
}
This is the main class that you can use to specify the setting values and default enabled features. For more information about settings, click here.
- Add a feature onto your project
You can hook your plug-in up onto several actions within PKHeX.Web.
For the purposes of this example, we will add a button that will be visible when editing a Pokemon, by using the IPokemonEditAction
hook:
public class DemoAction : IPokemonEditAction
{
public string Label => "Demo Action";
public string Description => "Demo action available when editing a pokemon";
public Task<Outcome> OnActionRequested(Pokemon pokemon)
{
return Outcome.Notify(message: "Action executed",
description: $"Action executed for pokemon: {pokemon.Species.Name}",
type: Outcome.Notification.NotificationType.Info).Completed();
}
}
This will simply add a button with label: Demo Action
when editing any Pokemon, and when clicking it will show a notification to the user with the content: Action executed for pokemon: Pikachu
Check here for more hook options
- Publishing the package
All the steps above should be enough to write your own plug-in and make it pluggable to PKHeX.Web
Right now there's no formal process for publishing it, if you want to make it available, open an issue in this repository mentioning:
- The description of the plug-in and what it does
- The code repository
Any plug-in compatible with PKHeX.Web should have exactly one class implementing the Settings
class, and that will be used to determine all metadata and settings of the plug-in.
The Settings
class requires an instance of a PlugInManifest
to be constructed which consists of metadata about the project:
public class PlugInDemo : Settings
{
public PlugInDemo() : base(Manifest)
{
}
private static readonly PlugInManifest Manifest = new PlugInManifest(
PlugInName: "Demo Plug-In",
Description: "Description of the plug-in", // optional
ProjectUrl: "https://my-plug-in.com", // optional
Information: "Some disclaimer to be shown in the plug-in settings page"); // optional
}
You may want to allow the user to change a few configuration values of your plug-in, and that's possible through the constructor:
public class PlugInDemo : Settings
{
public PlugInDemo() : base(Manifest)
{
this["Some boolean setting"] = new SettingValue.BooleanValue(true);
this["Some integer setting"] = new SettingValue.IntegerValue(1);
this["Some string setting"] = new SettingValue.StringValue("a value");
this["Some file setting"] = new SettingValue.FileValue([], string.Empty);
}
}
Right now the only supported setting value types are: BooleanValue
, IntegerValue
, StringValue
and FileValue
All setting values are persisted in the local storage, with the exception of FileValue
due to sizing limits its reference is still stored in the local storage, but the actual contents is stored in the IndexDb
All plug-in hooks defined in your project are disabled by default. If you want to have an action that's enabled by default, you have to intentionally specify that in the constructor:
public class PlugInDemo : Settings
{
public PlugInDemo() : base(Manifest)
{
EnabledByDefault<MaxRareCandiesButton>();
}
}
Plug-In hooks are the actual point of extension that's pluggable into PKHeX.Web, and there are several types that will help you extending the functionality that applies for your use case
A hook that happens every time an attribute of a Pokemon is changed
A hook that happens every time one saves a Pokemon
A hook that happens every time an item is added/removed/updated from your bag
Adds a button to the page when editing a Pokemon
Adds a button to the 'Stats' tab when editing a Pokemon
Adds a button to the home page of PKHeX.Web when a save is loaded
All plug-in actions should return an Outcome
out of an action varying from several types:
Simply no outcome, it will just return the execution
public Task<Outcome> OnActionRequested(Pokemon pokemon) => Outcome.Void.Completed();
Shows a pop-up notification when the action is finished:
public Task<Outcome> OnActionRequested(Pokemon pokemon) => Outcome.Notify(
message: "Applied legality",
description: $"{pokemon.Species.Name} made legal"
type: Outcome.Notification.NotificationType.Info).Completed();
Allows to forward to a custom page defined in your project:
public Task<Outcome> OnActionRequested(Pokemon pokemon) => Outcome.Page<MyCustomPage>(
path: "my-custom-page",
layout: Standard // optional parameter, options are: Standard or Empty
).Completed();
the example above forwards the user to the page under the path /my-custom-page
and will use MyCustomPage
as the content:
// MyCustomPage.razor
@inherits PkHexWebPlugInComponent
<div>This is a custom plug-in page</div>
All plug-in hooks have their own sand-box dependency injection container, and are allowed to inject:
-
IGameProvider
- allows to inspect currently aspect of the loaded game - Your plug-in settings class
Example:
public class MyQuickAction(
IGameProvider gameProvider,
PlugInDemo settings) : IQuickAction
{
public string Label => "Demo action";
public string Description => "Adds a button on the home page";
public IDisable.DisableInfo DisabledInfo => IDisable.Enabled;
public Task<Outcome> OnActionRequested()
{
if (gameProvider.IsLoaded && settings.GetBoolean("Can execute my action"))
return Outcome.Notify($"Executed for {gameProvider.LoadedGame.SaveVersion.Name}").Completed();
return Outcome.Void.Completed();
}
}