Compare commits
43 commits
Author | SHA1 | Date | |
---|---|---|---|
044d43652a | |||
|
7fb6bca1c5 | ||
|
b4f45f15b9 | ||
1ca0a23a4d | |||
|
ca2a027c07 | ||
|
ffdfa8f541 | ||
|
0b54e7aab2 | ||
531ed2ccfb | |||
|
0129fcb5c8 | ||
|
68f9440bb4 | ||
ded9db9092 | |||
|
4f91ab5be0 | ||
|
9bfcf9a213 | ||
|
a66a712421 | ||
|
cacaba167d | ||
aecad7e04c | |||
369d29bdec | |||
|
e842412924 | ||
|
75f6eda1b2 | ||
|
9609be2db4 | ||
|
7726c92523 | ||
|
847110e2e9 | ||
|
3328a0480c | ||
|
2c66f84544 | ||
d38e2718bb | |||
6277efd759 | |||
|
91665c92d1 | ||
fb5533dab9 | |||
dbfe38dd4d | |||
cf17e985ff | |||
c1abfe5453 | |||
cf3d34389d | |||
7d7cfcb11c | |||
26f4dfa864 | |||
196e2c43b5 | |||
6b0bfdd5ee | |||
9fff380502 | |||
128b976869 | |||
45430d50a1 | |||
|
2212d661be | ||
|
e2e308b353 | ||
|
af9dafddc8 | ||
|
b18e74e672 |
21 changed files with 453 additions and 37 deletions
64
.forgejo/workflows/create-release.yaml
Normal file
64
.forgejo/workflows/create-release.yaml
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
name: Create release on tag push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'release/*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Create release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install VoiceAttack
|
||||||
|
uses: alterNERDtive/setup-voiceattack-action@develop
|
||||||
|
with:
|
||||||
|
version: "1.10"
|
||||||
|
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup .Net
|
||||||
|
uses: actions/setup-dotnet@v2
|
||||||
|
with:
|
||||||
|
dotnet-version: '7.0.x'
|
||||||
|
|
||||||
|
- name: Restore dependencies
|
||||||
|
run: dotnet restore
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: dotnet build -c release
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: dotnet test
|
||||||
|
|
||||||
|
- name: Create NuGet package
|
||||||
|
run: dotnet pack -c release "VoiceAttack-Framework/VoiceAttack-Framework.csproj"
|
||||||
|
|
||||||
|
- name: Push NuGet package
|
||||||
|
run: dotnet nuget push "VoiceAttack-Framework/bin/Release/alterNERDtive.YAVAPF.*.nupkg" --source 'https://api.nuget.org/v3/index.json' --api-key ${{secrets.NUGET_AUTH_TOKEN}}
|
||||||
|
|
||||||
|
- name: Get release body
|
||||||
|
run: |
|
||||||
|
echo "release_body=$(cat CHANGELOG.md)" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: '>=1.20.1'
|
||||||
|
|
||||||
|
- name: Draft release
|
||||||
|
uses: https://gitea.com/actions/release-action@main
|
||||||
|
with:
|
||||||
|
body: ${{ env.release_body }}
|
||||||
|
files: |-
|
||||||
|
VoiceAttack-Framework/bin/Release/alterNERDtive.YAVAPF.*nupkg
|
||||||
|
VoiceAttack-Framework/bin/Release/net48/VoiceAttack-Framework.*
|
||||||
|
draft: true
|
||||||
|
api_key: '${{ secrets.RELEASE_TOKEN }}'
|
7
.github/workflows/create-release.yaml
vendored
7
.github/workflows/create-release.yaml
vendored
|
@ -19,12 +19,12 @@ jobs:
|
||||||
version: "1.10"
|
version: "1.10"
|
||||||
|
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup .Net
|
- name: Setup .Net
|
||||||
uses: actions/setup-dotnet@v2
|
uses: actions/setup-dotnet@v2
|
||||||
with:
|
with:
|
||||||
dotnet-version: '6.0.x'
|
dotnet-version: '7.0.x'
|
||||||
|
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
|
@ -44,6 +44,7 @@ jobs:
|
||||||
- name: Draft release
|
- name: Draft release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
artifacts: "VoiceAttack-Framework/bin/Release/alterNERDtive.YAVAPF.*nupkg"
|
artifacts: "VoiceAttack-Framework/bin/Release/alterNERDtive.YAVAPF.*nupkg,VoiceAttack-Framework/bin/Release/net48/VoiceAttack-Framework.*"
|
||||||
bodyFile: "CHANGELOG.md"
|
bodyFile: "CHANGELOG.md"
|
||||||
draft: true
|
draft: true
|
||||||
|
token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,3 +1,14 @@
|
||||||
# 0.1.0 (2022-07-11)
|
# devel
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
* [Commands interface](https://alternerdtive.github.io/YAVAPF/commands/).
|
||||||
|
* Optionally suppress the race condition warning on [setting command scoped
|
||||||
|
variables from the cached proxy
|
||||||
|
object](https://alternerdtive.github.io/YAVAPF/variables/#using-proxy-methods-vs-using-plugin-methods).
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# 0.1.0 (2022-07-11)
|
||||||
|
|
||||||
initial release
|
initial release
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
using alterNERDtive.Yavapf;
|
using alterNERDtive.Yavapf;
|
||||||
using VoiceAttack;
|
using VoiceAttack;
|
||||||
|
|
||||||
|
@ -143,6 +141,7 @@ namespace alterNERDtive.Example
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vaProxy">The current VoiceAttack proxy object.</param>
|
/// <param name="vaProxy">The current VoiceAttack proxy object.</param>
|
||||||
[Init]
|
[Init]
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Required by plugin API")]
|
||||||
public static void Init(VoiceAttackInitProxyClass vaProxy)
|
public static void Init(VoiceAttackInitProxyClass vaProxy)
|
||||||
{
|
{
|
||||||
Plugin.Log.Notice("This is the example Init handler method.");
|
Plugin.Log.Notice("This is the example Init handler method.");
|
||||||
|
@ -155,6 +154,7 @@ namespace alterNERDtive.Example
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vaProxy">The current VoiceAttack proxy object.</param>
|
/// <param name="vaProxy">The current VoiceAttack proxy object.</param>
|
||||||
[Exit]
|
[Exit]
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Required by plugin API")]
|
||||||
public static void Exit(VoiceAttackProxyClass vaProxy)
|
public static void Exit(VoiceAttackProxyClass vaProxy)
|
||||||
{
|
{
|
||||||
Plugin.Log.Notice("This is the example Exit handler method.");
|
Plugin.Log.Notice("This is the example Exit handler method.");
|
||||||
|
@ -206,6 +206,28 @@ namespace alterNERDtive.Example
|
||||||
$"This is the example handler for the plugin contexts “^foo.*” and “^.*bar.*”. It has been invoked with '{vaProxy.Context}'.");
|
$"This is the example handler for the plugin contexts “^foo.*” and “^.*bar.*”. It has been invoked with '{vaProxy.Context}'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An example handler for a context that runs additional VoiceAttack
|
||||||
|
/// commands.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vaProxy">The <see cref="VoiceAttackInvokeProxyClass"/>
|
||||||
|
/// proxy object.</param>
|
||||||
|
[Context("runcommandtest")]
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Required by plugin API")]
|
||||||
|
public static void RunCommandTestContext(VoiceAttackInvokeProxyClass vaProxy)
|
||||||
|
{
|
||||||
|
// “Just” runs a command with no further options
|
||||||
|
Plugin.Commands.Run("test command");
|
||||||
|
|
||||||
|
// Runs a command as a subcommand to the current command, and blocks
|
||||||
|
// until command execution finishes
|
||||||
|
Plugin.Commands.Run("test command", wait: true, subcommand: true);
|
||||||
|
|
||||||
|
Plugin.Commands.Run(
|
||||||
|
"command with parameters",
|
||||||
|
parameters: new dynamic[] { new string[] { "foo", "bar" }, new DateTime[] { DateTime.Now } });
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An example handler for changed <see cref="bool"/> variables. It only
|
/// An example handler for changed <see cref="bool"/> variables. It only
|
||||||
/// applies to the “isDay#” variable.
|
/// applies to the “isDay#” variable.
|
||||||
|
@ -214,6 +236,7 @@ namespace alterNERDtive.Example
|
||||||
/// <param name="from">The old value of the variable.</param>
|
/// <param name="from">The old value of the variable.</param>
|
||||||
/// <param name="to">The new value of the variable.</param>
|
/// <param name="to">The new value of the variable.</param>
|
||||||
[Bool("isDay#")]
|
[Bool("isDay#")]
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Required by plugin API")]
|
||||||
public static void DayChanged(string name, bool? from, bool? to)
|
public static void DayChanged(string name, bool? from, bool? to)
|
||||||
{
|
{
|
||||||
Plugin.Log.Notice($"This is the example handler for changed bool variables. It is now {(to ?? false ? "day" : "night")}.");
|
Plugin.Log.Notice($"This is the example handler for changed bool variables. It is now {(to ?? false ? "day" : "night")}.");
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsPublishable>False</IsPublishable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -18,6 +20,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="VoiceAttack">
|
<Reference Include="VoiceAttack">
|
||||||
<HintPath>C:\Program Files\VoiceAttack\VoiceAttack.exe</HintPath>
|
<HintPath>C:\Program Files\VoiceAttack\VoiceAttack.exe</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
using alterNERDtive.Yavapf;
|
using alterNERDtive.Yavapf;
|
||||||
|
|
||||||
namespace alterNERDtive.Example
|
namespace alterNERDtive.Example
|
||||||
|
|
|
@ -17,9 +17,6 @@ the inner workings of VoiceAttack as possible.
|
||||||
You can find [comprehensive documentation on Github
|
You can find [comprehensive documentation on Github
|
||||||
Pages](https://alterNERDtive.github.io/YAVAPF).
|
Pages](https://alterNERDtive.github.io/YAVAPF).
|
||||||
|
|
||||||
Or at least you will once this is in a presentable state and I have actually
|
|
||||||
written the documentation :)
|
|
||||||
|
|
||||||
There is also an [example plugin on
|
There is also an [example plugin on
|
||||||
Github](https://github.com/alterNERDtive/YAVAPF/tree/release/ExamplePlugin).
|
Github](https://github.com/alterNERDtive/YAVAPF/tree/release/ExamplePlugin).
|
||||||
|
|
||||||
|
|
2
StyleCop.ruleset
Normal file
2
StyleCop.ruleset
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RuleSet Name="StyleCop.Analyzers rules with default action" Description="StyleCop.Analyzers with default action. Rules with IsEnabledByDefault = false are disabled." ToolsVersion="17.0" />
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net48</TargetFramework>
|
<TargetFramework>net48</TargetFramework>
|
||||||
|
@ -6,17 +6,19 @@
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.9.0" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -18,6 +18,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
requirements.txt = requirements.txt
|
requirements.txt = requirements.txt
|
||||||
stylecop.json = stylecop.json
|
stylecop.json = stylecop.json
|
||||||
|
StyleCop.ruleset = StyleCop.ruleset
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{1BE45F7D-E6DE-49D2-A906-5CC9CD49B639}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{1BE45F7D-E6DE-49D2-A906-5CC9CD49B639}"
|
||||||
|
@ -44,8 +45,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{3FE46F37-0
|
||||||
docs\contexts.md = docs\contexts.md
|
docs\contexts.md = docs\contexts.md
|
||||||
docs\events.md = docs\events.md
|
docs\events.md = docs\events.md
|
||||||
docs\extra.css = docs\extra.css
|
docs\extra.css = docs\extra.css
|
||||||
docs\gettingstarted.md = docs\gettingstarted.md
|
|
||||||
docs\faq.md = docs\faq.md
|
docs\faq.md = docs\faq.md
|
||||||
|
docs\gettingstarted.md = docs\gettingstarted.md
|
||||||
docs\index.md = docs\index.md
|
docs\index.md = docs\index.md
|
||||||
docs\logging.md = docs\logging.md
|
docs\logging.md = docs\logging.md
|
||||||
docs\variables.md = docs\variables.md
|
docs\variables.md = docs\variables.md
|
||||||
|
|
|
@ -24,3 +24,4 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "because that’s my name", Scope = "namespace", Target = "~N:alterNERDtive.Yavapf")]
|
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "because that’s my name", Scope = "namespace", Target = "~N:alterNERDtive.Yavapf")]
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "have to do that to make arrays nullable, fam", Scope = "type", Target = "~T:alterNERDtive.Yavapf.VoiceAttackCommands")]
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFrameworks>net48</TargetFrameworks>
|
<TargetFrameworks>net48</TargetFrameworks>
|
||||||
<RootNamespace>alterNERDtive.Yavapf</RootNamespace>
|
<RootNamespace>alterNERDtive.Yavapf</RootNamespace>
|
||||||
<PackageId>alterNERDtive.YAVAPF</PackageId>
|
<PackageId>alterNERDtive.YAVAPF</PackageId>
|
||||||
<Version>0.1.0</Version>
|
<Version>0.2.0</Version>
|
||||||
<Company>alterNERDtive</Company>
|
<Company>alterNERDtive</Company>
|
||||||
<Authors>alterNERDtive</Authors>
|
<Authors>alterNERDtive</Authors>
|
||||||
<Description>YAVAPF is yet another VoiceAttack plugin framework.</Description>
|
<Description>YAVAPF is yet another VoiceAttack plugin framework.</Description>
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
<PackageTags>VoiceAttack;plugin;framework</PackageTags>
|
<PackageTags>VoiceAttack;plugin;framework</PackageTags>
|
||||||
<NeutralLanguage>en</NeutralLanguage>
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
<Title>Yet Another VoiceAttack Plugin Framework</Title>
|
<Title>Yet Another VoiceAttack Plugin Framework</Title>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
@ -26,6 +26,8 @@
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -41,6 +43,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="VoiceAttack">
|
<Reference Include="VoiceAttack">
|
||||||
<HintPath>C:\Program Files\VoiceAttack\VoiceAttack.exe</HintPath>
|
<HintPath>C:\Program Files\VoiceAttack\VoiceAttack.exe</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
|
|
187
VoiceAttack-Framework/VoiceAttackCommands.cs
Normal file
187
VoiceAttack-Framework/VoiceAttackCommands.cs
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
// <copyright file="VoiceAttackCommands.cs" company="alterNERDtive">
|
||||||
|
// Copyright 2022 alterNERDtive.
|
||||||
|
//
|
||||||
|
// This file is part of YAVAPF.
|
||||||
|
//
|
||||||
|
// YAVAPF is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// YAVAPF is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
using VoiceAttack;
|
||||||
|
|
||||||
|
namespace alterNERDtive.Yavapf
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an interface to run VoiceAttack commands from a plugin.
|
||||||
|
/// </summary>
|
||||||
|
public class VoiceAttackCommands
|
||||||
|
{
|
||||||
|
private readonly VoiceAttackInitProxyClass vaProxy;
|
||||||
|
private readonly VoiceAttackLog log;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="VoiceAttackCommands"/>
|
||||||
|
/// class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vaProxy">The <see cref="VoiceAttackInitProxyClass"/>
|
||||||
|
/// proxy object.</param>
|
||||||
|
/// <param name="log">The <see cref="VoiceAttackLog"/> object.</param>
|
||||||
|
internal VoiceAttackCommands(VoiceAttackInitProxyClass vaProxy, VoiceAttackLog log) => (this.vaProxy, this.log) = (vaProxy, log);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a VoiceAttack command.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">The name of the command.</param>
|
||||||
|
/// <param name="logMissing">Whether or not to log a message if the
|
||||||
|
/// command in question does not exist in the current profile.</param>
|
||||||
|
/// <param name="wait">Whether to wait for the command to finish
|
||||||
|
/// executing before returning.</param>
|
||||||
|
/// <param name="subcommand">Whether the called command should be run as
|
||||||
|
/// a subcommand to the current command context.</param>
|
||||||
|
/// <param name="parameters">The parameters for the command. Has to be
|
||||||
|
/// an array of arrays, with the inner arrays being of a valid
|
||||||
|
/// Voiceattack variable type.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown if the name of the
|
||||||
|
/// command is missing.</exception>
|
||||||
|
public void Run(string command, bool logMissing = true, bool wait = false, bool subcommand = false, dynamic[]? parameters = null)
|
||||||
|
{
|
||||||
|
_ = command ?? throw new ArgumentNullException("command");
|
||||||
|
|
||||||
|
if (this.vaProxy.Command.Exists(command))
|
||||||
|
{
|
||||||
|
this.log.Debug($"Parsing arguments for command '{command}' …");
|
||||||
|
|
||||||
|
string[]? strings = null;
|
||||||
|
int[]? integers = null;
|
||||||
|
decimal[]? decimals = null;
|
||||||
|
bool[]? booleans = null;
|
||||||
|
DateTime[]? dates = null; // this might not work!
|
||||||
|
|
||||||
|
foreach (var values in parameters ?? Enumerable.Empty<object>())
|
||||||
|
{
|
||||||
|
switch (values)
|
||||||
|
{
|
||||||
|
case bool[] b:
|
||||||
|
booleans = b;
|
||||||
|
break;
|
||||||
|
case DateTime[] d:
|
||||||
|
dates = d;
|
||||||
|
break;
|
||||||
|
case decimal[] d:
|
||||||
|
decimals = d;
|
||||||
|
break;
|
||||||
|
case int[] i:
|
||||||
|
integers = i;
|
||||||
|
break;
|
||||||
|
case string[] s:
|
||||||
|
strings = s;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log.Debug($"Running command '{command}' …");
|
||||||
|
|
||||||
|
this.vaProxy.Command.Execute(
|
||||||
|
CommandPhrase: command,
|
||||||
|
WaitForReturn: wait,
|
||||||
|
AsSubcommand: subcommand,
|
||||||
|
CompletedAction: null,
|
||||||
|
PassedText: strings == null ? null : $"\"{string.Join<string>("\";\"", strings)}\"",
|
||||||
|
PassedIntegers: integers == null ? null : string.Join<int>(";", integers),
|
||||||
|
PassedDecimals: decimals == null ? null : string.Join<decimal>(";", decimals),
|
||||||
|
PassedBooleans: booleans == null ? null : string.Join<bool>(";", booleans),
|
||||||
|
PassedDates: dates == null ? null : string.Join<DateTime>(";", dates));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (logMissing)
|
||||||
|
{
|
||||||
|
this.log.Warn($"Tried running missing command '{command}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a VoiceAttack command with a given list of prefixes. Will run
|
||||||
|
/// `prefix.command` for each prefix.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefixes">The list of prefixes.</param>
|
||||||
|
/// <param name="command">The name of the command.</param>
|
||||||
|
/// <param name="logMissing">Whether or not to log a message if the
|
||||||
|
/// command in question does not exist in the current profile.</param>
|
||||||
|
/// <param name="wait">Whether to wait for the command to finish
|
||||||
|
/// executing before returning.</param>
|
||||||
|
/// <param name="subcommand">Whether the called command should be run as
|
||||||
|
/// a subcommand to the current command context.</param>
|
||||||
|
/// <param name="parameters">The parameters for the command.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown if the name of the
|
||||||
|
/// command is missing.</exception>
|
||||||
|
public void RunAll(IEnumerable<string> prefixes, string command, bool logMissing = true, bool wait = false, bool subcommand = false, dynamic[][]? parameters = null)
|
||||||
|
{
|
||||||
|
foreach (string prefix in prefixes)
|
||||||
|
{
|
||||||
|
this.Run($"{prefix}.{command}", logMissing, wait, subcommand, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a VoiceAttack event command. Event commands are enclosed in
|
||||||
|
/// double paratheses by convention, they will be added automatically.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the event.</param>
|
||||||
|
/// <param name="logMissing">Whether or not to log a message if the
|
||||||
|
/// command in question does not exist in the current profile.</param>
|
||||||
|
/// <param name="wait">Whether to wait for the command to finish
|
||||||
|
/// executing before returning.</param>
|
||||||
|
/// <param name="subcommand">Whether the called command should be run as
|
||||||
|
/// a subcommand to the current command context.</param>
|
||||||
|
/// <param name="parameters">The parameters for the command. Has to be
|
||||||
|
/// an array of arrays, with the inner arrays being of a valid
|
||||||
|
/// Voiceattack variable type.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown if the name of the
|
||||||
|
/// command is missing.</exception>
|
||||||
|
public void TriggerEvent(string name, bool logMissing = true, bool wait = false, bool subcommand = false, dynamic[]? parameters = null)
|
||||||
|
{
|
||||||
|
this.Run($"(({name}))", logMissing, wait, subcommand, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a VoiceAttack event command with a given list of prefixes.
|
||||||
|
/// Event commands are enclosed in double paratheses by convention, they
|
||||||
|
/// will be added automatically. Will run `((prefix.name))` for each
|
||||||
|
/// prefix.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefixes">The list of prefixes.</param>
|
||||||
|
/// <param name="name">The name of the event.</param>
|
||||||
|
/// <param name="logMissing">Whether or not to log a message if the
|
||||||
|
/// command in question does not exist in the current profile.</param>
|
||||||
|
/// <param name="wait">Whether to wait for the command to finish
|
||||||
|
/// executing before returning.</param>
|
||||||
|
/// <param name="subcommand">Whether the called command should be run as
|
||||||
|
/// a subcommand to the current command context.</param>
|
||||||
|
/// <param name="parameters">The parameters for the command. Has to be
|
||||||
|
/// an array of arrays, with the inner arrays being of a valid
|
||||||
|
/// Voiceattack variable type.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown if the name of the
|
||||||
|
/// command is missing.</exception>
|
||||||
|
public void TriggerEventAll(IEnumerable<string> prefixes, string name, bool logMissing = true, bool wait = false, bool subcommand = false, dynamic[][]? parameters = null)
|
||||||
|
{
|
||||||
|
foreach (string prefix in prefixes)
|
||||||
|
{
|
||||||
|
this.Run($"(({prefix}.{name}))", logMissing, wait, subcommand, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,9 +17,6 @@
|
||||||
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
using VoiceAttack;
|
using VoiceAttack;
|
||||||
|
|
||||||
namespace alterNERDtive.Yavapf
|
namespace alterNERDtive.Yavapf
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
using VoiceAttack;
|
using VoiceAttack;
|
||||||
|
|
||||||
namespace alterNERDtive.Yavapf
|
namespace alterNERDtive.Yavapf
|
||||||
|
|
|
@ -17,10 +17,6 @@
|
||||||
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
// along with YAVAPF. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
@ -33,6 +29,7 @@ namespace alterNERDtive.Yavapf
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class VoiceAttackPlugin
|
public class VoiceAttackPlugin
|
||||||
{
|
{
|
||||||
|
private VoiceAttackCommands? commands;
|
||||||
private VoiceAttackLog? log;
|
private VoiceAttackLog? log;
|
||||||
private VoiceAttackInitProxyClass? vaProxy;
|
private VoiceAttackInitProxyClass? vaProxy;
|
||||||
|
|
||||||
|
@ -120,6 +117,17 @@ namespace alterNERDtive.Yavapf
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected string? Guid { get; set; }
|
protected string? Guid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="VoiceAttackCommands"/> instance the plugin uses
|
||||||
|
/// to run commands.
|
||||||
|
///
|
||||||
|
/// You can use this to run your own commands.
|
||||||
|
/// </summary>
|
||||||
|
protected VoiceAttackCommands Commands
|
||||||
|
{
|
||||||
|
get => this.commands ??= new VoiceAttackCommands(this.Proxy, this.Log);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the <see cref="VoiceAttackLog"/> instance the plugin uses to
|
/// Gets the <see cref="VoiceAttackLog"/> instance the plugin uses to
|
||||||
/// log to the VoiceAttack event log.
|
/// log to the VoiceAttack event log.
|
||||||
|
@ -139,11 +147,13 @@ namespace alterNERDtive.Yavapf
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of the variable.</typeparam>
|
/// <typeparam name="T">The type of the variable.</typeparam>
|
||||||
/// <param name="name">The name of the variable.</param>
|
/// <param name="name">The name of the variable.</param>
|
||||||
|
/// <param name="suppressWarning">Whether to suppress the race condition
|
||||||
|
/// warning on accessing command scoped variables.</param>
|
||||||
/// <returns>The value of the variable. Can be null.</returns>
|
/// <returns>The value of the variable. Can be null.</returns>
|
||||||
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
|
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
|
||||||
protected T? Get<T>(string name)
|
protected T? Get<T>(string name, bool suppressWarning = false)
|
||||||
{
|
{
|
||||||
if (name.StartsWith("~"))
|
if (name.StartsWith("~") && !suppressWarning)
|
||||||
{
|
{
|
||||||
this.Log.Warn(
|
this.Log.Warn(
|
||||||
$"Accessing command scoped variable '{name}' outside of its context proxy object. This might lead to race conditions.");
|
$"Accessing command scoped variable '{name}' outside of its context proxy object. This might lead to race conditions.");
|
||||||
|
@ -161,10 +171,12 @@ namespace alterNERDtive.Yavapf
|
||||||
/// <typeparam name="T">The type of the variable.</typeparam>
|
/// <typeparam name="T">The type of the variable.</typeparam>
|
||||||
/// <param name="name">The name of the variable.</param>
|
/// <param name="name">The name of the variable.</param>
|
||||||
/// <param name="value">The value of the variable. Can not be null.</param>
|
/// <param name="value">The value of the variable. Can not be null.</param>
|
||||||
|
/// <param name="suppressWarning">Whether to suppress the race condition
|
||||||
|
/// warning on accessing command scoped variables.</param>
|
||||||
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
|
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
|
||||||
protected void Set<T>(string name, T? value)
|
protected void Set<T>(string name, T? value, bool suppressWarning = false)
|
||||||
{
|
{
|
||||||
if (name.StartsWith("~"))
|
if (name.StartsWith("~") && !suppressWarning)
|
||||||
{
|
{
|
||||||
this.Log.Warn(
|
this.Log.Warn(
|
||||||
$"Accessing command scoped variable '{name}' outside of its context proxy object. This might lead to race conditions.");
|
$"Accessing command scoped variable '{name}' outside of its context proxy object. This might lead to race conditions.");
|
||||||
|
@ -181,10 +193,12 @@ namespace alterNERDtive.Yavapf
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of the variable.</typeparam>
|
/// <typeparam name="T">The type of the variable.</typeparam>
|
||||||
/// <param name="name">The name of the variable.</param>
|
/// <param name="name">The name of the variable.</param>
|
||||||
|
/// <param name="suppressWarning">Whether to suppress the race condition
|
||||||
|
/// warning on accessing command scoped variables.</param>
|
||||||
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
|
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
|
||||||
protected void Unset<T>(string name)
|
protected void Unset<T>(string name, bool suppressWarning = false)
|
||||||
{
|
{
|
||||||
if (name.StartsWith("~"))
|
if (name.StartsWith("~") && !suppressWarning)
|
||||||
{
|
{
|
||||||
this.Log.Warn(
|
this.Log.Warn(
|
||||||
$"Accessing command scoped variable '{name}' outside of its context proxy object. This might lead to race conditions.");
|
$"Accessing command scoped variable '{name}' outside of its context proxy object. This might lead to race conditions.");
|
||||||
|
|
|
@ -1,3 +1,93 @@
|
||||||
# Executing VoiceAttack Commands
|
# Executing VoiceAttack Commands
|
||||||
|
|
||||||
Not implemented yet.
|
VoicAttack’s plugin API allows you to run commands from your plugin:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
vaProxy.Command.Execute(
|
||||||
|
string CommandPhrase,
|
||||||
|
bool WaitForReturn,
|
||||||
|
bool AsSubcommand,
|
||||||
|
Action<Guid?> CompletedAction,
|
||||||
|
string PassedText,
|
||||||
|
srting PassedIntegers,
|
||||||
|
string PassedDecimals,
|
||||||
|
string PassedBooleans,
|
||||||
|
string PassedDates);
|
||||||
|
```
|
||||||
|
|
||||||
|
None of those parameters are optional, and the arguments have to be passed as
|
||||||
|
semicolon delimited strings. With extra hassle around quoting `string`
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
YAVAPF aims to make this API a little more comfortable to work with.
|
||||||
|
|
||||||
|
## Running a Command
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Plugin.Commands.Run(
|
||||||
|
string command,
|
||||||
|
bool logMissing = true,
|
||||||
|
bool wait = false,
|
||||||
|
bool subcommand = false,
|
||||||
|
dynamic[]? parameters = null);
|
||||||
|
```
|
||||||
|
|
||||||
|
The main difference here is that all parameters apart from the command name are
|
||||||
|
now _optional_. You can also now pass arguments to the command as typed arrays:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Plugin.Commands.Run(
|
||||||
|
"example command",
|
||||||
|
parameters: new dynamic[]
|
||||||
|
{
|
||||||
|
new string[] { "text value", "other text value" },
|
||||||
|
new bool[] { true }
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The ability to pass a callback `Action<Guid?>` is not exposed. The only
|
||||||
|
information this `Action` can ever receive is the `Guid` of the command that has
|
||||||
|
been run; setting such a `Guid` in a profile though is a fairly involved
|
||||||
|
process, and exporting / importing the profile might not even preserve it.
|
||||||
|
Tl;dr: it is kind of useless right now.
|
||||||
|
|
||||||
|
## Running a Command with Prefixes
|
||||||
|
|
||||||
|
The `RunAll` method lets you run a command with multiple prefixes. This is
|
||||||
|
especially useful if your plugin accompanies a set of multiple VoiceAttack
|
||||||
|
profiles, [like my Elite Dangerous profiles and their correspondingp
|
||||||
|
plugins](https://alterNERDtive.github.io/VoiceAttack-profiles).
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Plugin.Commands.RunAll(new string[] { "EliteAttack", "RatAttack" }, "startup", …);
|
||||||
|
```
|
||||||
|
|
||||||
|
Prefixes are prepended to the command name with a dot. The line above would run
|
||||||
|
the `EliteAttack.startup` and `RatAttack.startup` commands.
|
||||||
|
|
||||||
|
## Running an Event
|
||||||
|
|
||||||
|
VoiceAttack does not actually have a concept of running commands on events. The
|
||||||
|
workaround is to have a naming convention for VoiceAttack “event” commands.
|
||||||
|
|
||||||
|
YAVAPF borrows the [`((command))` convention from
|
||||||
|
EDDI](https://github.com/EDCD/EDDI/wiki/VoiceAttack-Integration#running-commands-on-eddi-events).
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Plugin.Commands.TriggerEvent("some event", …);
|
||||||
|
```
|
||||||
|
|
||||||
|
This would run the `((some event))` command in VoiceAttack. Optional parameters
|
||||||
|
are the same as for [the `Run` method](commands.md#running-a-command).
|
||||||
|
|
||||||
|
## Running an Event with Prefixes
|
||||||
|
|
||||||
|
Similar to [`RunAll`](commands.md#running-a-command-with-prefixes),
|
||||||
|
`TriggerEventAll` exists.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Plugin.Commands.TriggerEventAll(new string[] { "profile", "otherprofile" }, "event", …);
|
||||||
|
```
|
||||||
|
|
||||||
|
This would run the `((profile.event))` and `((otherprofile.event))` comands in
|
||||||
|
VoiceAttack.
|
||||||
|
|
|
@ -23,10 +23,21 @@ Github](https://github.com/alterNERDtive/YAVAPF/tree/release/ExamplePlugin).
|
||||||
* [x] Handlers for variable changed events
|
* [x] Handlers for variable changed events
|
||||||
* [x] Logging to the VoiceAttack event log
|
* [x] Logging to the VoiceAttack event log
|
||||||
* [ ] Logging to a log file
|
* [ ] Logging to a log file
|
||||||
* [ ] Wrapper for executing commands
|
* [ ] separate full debug log
|
||||||
|
* [x] Wrapper for executing commands
|
||||||
|
* [ ] Plugin options, separate from handling “normal” variables
|
||||||
|
* [ ] default values
|
||||||
|
* [ ] descriptions
|
||||||
|
* [ ] auto save / load between VoiceAttack runs¹
|
||||||
|
* [ ] profile specific
|
||||||
|
* [ ] global
|
||||||
|
* [ ] bootstrapping voice commands for changing options
|
||||||
|
* [ ] GUI support
|
||||||
* [ ] Miscellaneous VoiceAttack proxy functionality
|
* [ ] Miscellaneous VoiceAttack proxy functionality
|
||||||
* [ ] Full unit test coverage 😬
|
* [ ] Full unit test coverage 😬
|
||||||
|
|
||||||
|
¹ Will probably require changes in VoiceAttack that I have already requested.
|
||||||
|
|
||||||
## Need Help / Want to Contribute?
|
## Need Help / Want to Contribute?
|
||||||
|
|
||||||
Have a look at [the FAQ](faq.md). If your problem persists, please [file an
|
Have a look at [the FAQ](faq.md). If your problem persists, please [file an
|
||||||
|
|
|
@ -58,7 +58,7 @@ Its parameter is not case sensitive.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
Plugin.Log.LogLevel = LogLevel.WARN;
|
Plugin.Log.LogLevel = LogLevel.WARN;
|
||||||
Plugin.Log.SetLogLevel = "info";
|
Plugin.Log.SetLogLevel("info");
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also set the log level from a VoiceAttack command directly by simply
|
You can also set the log level from a VoiceAttack command directly by simply
|
||||||
|
|
|
@ -93,6 +93,19 @@ private static void TestContext(VoiceAttackInvokeProxyClass vaProxy)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This will log a warning to the VoiceAttack event log.
|
||||||
|
|
||||||
|
You can, if you are sure that you will _not_ run into a race condition, suppress
|
||||||
|
said warning:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
[Context("test")]
|
||||||
|
private static void TestContext(VoiceAttackInvokeProxyClass vaProxy)
|
||||||
|
{
|
||||||
|
string test = Plugin.Get<string>("~test", suppressWarning: true);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Getting Variable Values
|
## Getting Variable Values
|
||||||
|
|
||||||
To get the value of a variable, invoke the `Get<T>(string name)` method of your
|
To get the value of a variable, invoke the `Get<T>(string name)` method of your
|
||||||
|
|
Loading…
Reference in a new issue