Skip to content

Plugins ru RU

GitHub Action edited this page Nov 27, 2020 · 41 revisions

Плагины

Начиная с ASF V4, программа включает в себя поддержку пользовательских плагинов, которые могут загружаться в процессе выполнения. Плагины позволяют вам изменять поведение ASF, например добавляя дополнительные команды, новую логику принятия обменов или полную интеграцию со сторонними сервисами и API.


Для Пользователей

ASF загружает плагины из папки plugins расположенной в вашей папке с ASF. Рекомендованной практикой является поддержание отдельной папки для каждого плагина, который вы хотите использовать, она может иметь имя в соответствии с его названием, например MyPlugin. Это даст в результате структуру каталогов plugins/MyPlugin. Наконец, все двоичные файлы плагина следует положить в эту выделенную папку, и ASF обнаружит и начнёт использовать ваш плагин после перезапуска.

Обычно разработчики плагинов будут публиковать плагины в форме zip-файла, с уже подготовленной для вас структурой, так что вам будет достаточно распаковать этот zip-архив в папку plugins, что создаст необходимую папку автоматически.

Если плагин успешно загружен - вы увидите его название и версию в журнале ASF. В случае вопросов или проблем, связанных с используемым плагином, вам следует обратиться к разработчикам плагина.

Вы можете найти некоторые плагины в нашем разделе "Сторонние разработки".

Помните о том, что плагины ASF могут быть вредоносными. Вам всегда следует убедиться, что вы пользуетесь только теми плагинами, разработчикам которых вы можете доверять. Разработчики ASF не могут вам гарантировать обычных преимуществ ASF (как например отсутствие вирусов или гарантию отсутствия VAC) если вы решите использовать какие-либо пользовательские плагины. Мы также не можем поддерживать конфигурации с использованием пользовательских плагинов, поскольку вы больше не используете чистый код ASF.


Для разработчиков

Плагины это стандартные библиотеки .NET, унаследованные от общего интерфейса IPlugin в ASF. Вы можете разрабатывать плагины полностью независимо от развития основной ветки ASF, и повторно использовать их в текущей и будущей версиях ASF, до тех пор пока API остаётся совместимым. Система плагинов, используемая в ASF, основана на System.Composition, ранее известном как Managed Extensibility Framework, который позволяет ASF обнаруживать и загружать ваши библиотеки в процессе исполнения.


Начало работы

Ваш проект должен быть стандартной библиотекой .NET с целевой платформой соответствующей желаемой версии ASF, как описано в разделе "Компиляция". Мы рекомендуем целевую платформу .NET Core, но плагины могут быть и для .NET Framework.

Проект должен ссылаться на сборку ArchiSteamFarm, либо в виде собранной библиотеки ArchiSteamFarm.dll которую вы скачиваете как часть выпуска, либо в виде исходного проекта (например если вы добавили дерево ASF в качестве под-модуля). Это позволит вам получить доступ к структурам, методам и свойствам ASF, в особенностью к ядру интерфейса IPlugin, которое вам понадобится на следующем этапе. Проект также должен иметь ссылку как минимум на System.Composition.AttributedModel, что позволит вам сделать [Export] вашего IPlugin для использования в ASF. В добавок к этому, вам может захотеться/понадобиться сослаться на другие общие библиотеки с целью интерпретировать структуры данных, которые вам предоставлены в некоторых интерфейсах, но если они не являются необходимыми - этого будет пока достаточно.

Если вы сделали всё правильно, ваш файл csproj будет иметь примерно такой вид:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" Version="*" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="ArchiSteamFarm" HintPath="C:\\Path\To\Downloaded\ArchiSteamFarm.dll" />

    <!-- If building as part of ASF source tree, use this instead of <Reference> above -->
    <!-- <ProjectReference Include="C:\\Path\To\ArchiSteamFarm\ArchiSteamFarm.csproj" ExcludeAssets="all" Private="false" /> -->
  </ItemGroup>
</Project>

С точки зрения кода, класс вашего плагина должен быть унаследован от интерфейса IPlugin (либо напрямую, либо косвенно через наследование одного из специализированных интерфейсов, как например IASF) и иметь аттрибут [Export(typeof(IPlugin))] чтобы быть распознанным ASF в процессе работы. Самый простой пример реализации всего этого будет следующим:

using System;
using System.Composition;
using ArchiSteamFarm;
using ArchiSteamFarm.Plugins;

namespace YourNamespace.YourPluginName {
    [Export(typeof(IPlugin))]
    public sealed class YourPluginName : IPlugin {
        public string Name => nameof(YourPluginName);
        public Version Version => typeof(YourPluginName).Assembly.GetName().Version;

        public void OnLoaded() {
            ASF.ArchiLogger.LogGenericInfo("Meow");
        }
    }
}

Чтобы воспользоваться вашим плагином, его надо сначала скомпилировать. Вы можете сделать это либо из своей IDE, или из корневой папки вашего проекта с помощью команды:

# Если у вас самостоятельный проект (нет нужды указывать имя, поскольку оно только одно)
dotnet publish -c "Release" -o "out"

# Если ваш проект часть дерева ASF (чтобы избежать компиляции необязательных частей)
dotnet publish YourPluginName -c "Release" -o "out"

После этого, ваш плагин готов к развертыванию. Как именно вы хотите распространять и публиковать ваш плагин - решать вам, но мы рекомендуем создать zip-архив c единственной папкой YourNamespace.YourPluginName, внутри которой находится ваш скомпилированный плагин вместе со всеми зависимостями. Таким образом пользователю нужно будет просто распаковать ваш zip-архив в его папку plugins, и ничего более.

Это самый простой сценарий, просто чтобы помочь вам начать. У нас также есть проект ExamplePlugin который представляет собой пример интерфейсов и действий, которые вы можете использовать в своём плагине, включая полезные комментарии. Не стесняйтесь заглянуть туда, если предпочитаете учиться по работающему коду, или сами изучите пространство имён ArchiSteamFarm.Plugins и обратитесь ко встроенной документации чтобы узнать все доступные возможности.


Доступность API

ASF, помимо того к чему вы имеете доступ через сами интерфейсы, открывает вам множество своих внутренних API, которые вы можете использовать для расширения функционала. Например, если вы хотите отправить новый вид веб-запроса к Steam, вам не нужно изобретать всё с нуля, особенно решение всех тех проблем, с которыми мы столкнулись раньше вас. Просто используйте наш Bot.ArchiWebHandler, который предоставит вам возможность использовать множество методов UrlWithSession(), и возьмёт на себя обработку всех низкоуровневых задач, таких как аутентификация, обновление сессии или ограничение частоты запросов. Аналогично, для отправки веб-запросов за пределами платформы Steam, вы можете использовать стандартный класс .NET HttpClient, но гораздо лучшей идеей будет использовать доступный вам Bot.ArchiWebHandler.WebBrowser, который, опять же, предоставит вам свою помощь, например в части повторных запросов в случае неудачи.

У нас очень открытая политика относительно доступности нашего API, поэтому если вы хотели бы использовать что-то, что ASF уже включает в себя, просто откройте issue и объясните в нём планируемое использование наших внутренних API ASF. Мы скорее всего не будем иметь ничего против, если предполагаемое вами использование имеет смысл. Для нас просто невозможно открыть всё, что кто-то может захотеть использовать, поэтому мы открыли только то, что кажется нам осмысленным, и ожидаем ваших запросов в случае если вы хотите получить доступ к чему-то, что ещё не public. Это включает в себя также все предложения по поводу новых интерфейсов IPlugin, которые имеет смысл добавить чтобы расширить существующий функционал.

Фактически, внутренние API ASF это единственное реальное ограничение того, что может делать ваш плагин. Ничто не остановит вас, например, если вы добавите в своё приложение библиотеку Discord.Net и создадите мост между вашим Discord-ботом и командами ASF, поскольку ваш плагин может иметь свои собственные зависимости. Возможности безграничны, и мы изо всех сил старались дать вам максимум свободы и гибкости в вашем плагине, поэтому нет никаких искусственных ограничений на что-либо, просто мы не до конца уверены, какие части ASF необходимы вам для разработки плагинов (и это можно решить просто дав нам знать, или даже без этого вы всегда можете воссоздать необходимый функционал).


Совместимость API

Важно подчеркнуть, что ASF это пользовательское приложение, а не обычная библиотека с фиксированными API, на которых можно безусловно основываться. Это означает что вы не можете предположить что ваш плагин, будучи однажды скомпилирован, продолжит работать также и во всех будущих выпусках ASF, это сделало бы невозможным дальнейшее развитие программы, а невозможность адаптироваться к постоянным изменениям в Steam ради обратной совместимости в нашем случае недопустима. Это должно быть для вас логичным, но важно подчеркнуть этот факт.

Мы будем стараться поддерживать общедоступные части ASF стабильными и работающими, но мы не будем себя сдерживать если возникнет необходимость поломать совместимость, и при этом мы будем следовать нашей политике устаревания. Это в особенности касается внутренних структур ASF, которые доступны вам как часть инфраструктуры ASF, описанной выше (например, ArchiWebHandler), которые могут быть улучшены (и потому переписаны) как часть улучшений ASF в одной из будущих версий. Мы будем стараться информировать об устаревшем функционале в списке изменений, и выдавать соответствующие предупреждения в процессе работы. У нас нет цели переписывать всё подряд только ради того чтобы переписать, так что вы можете быть относительно уверены в том, что следующая минорная версия не сломает полностью ваш плагин только потому, что увеличился номер версии, но вам стоит следить за списками изменений и периодически проверять, что всё работает.


Зависимости плагинов

Ваш плагин будет включать в себя по умолчанию как минимум две зависимости, ссылку на ArchiSteamFarm для внутренних API и PackageReference из System.Composition.AttributedModel, что необходимо чтобы ASF мог распознать ваш плагин. В добавок к этому, он может иметь больше зависимостей, если они нужны для того, что вы решили реализовать в своём плагине (например, библиотеку Discord.Net если вы решили сделать интеграцию с Discord).

The output of your build will include your core YourPluginName.dll library, as well as all the dependencies that you've referenced. Since you're developing a plugin to already-working program, you don't have to, and even shouldn't include dependencies that ASF already includes, for example ArchiSteamFarm, SteamKit2 or Newtonsoft.Json. Удаление из вашей сборки всех зависимостей, общих с ASF, не является обязательным требованием для работы плагина, но это существенно уменьшит потребляемую память и размер вашего плагина, а также увеличит быстродействие, благодаря тому что ASF будет разделять свои зависимости с вами, и будет загружать только те библиотеки, о которых ему неизвестно.

In general, it's a recommended practice to include only those libraries that ASF either doesn't include, or includes in the wrong/incompatible version. Examples of those would be obviously YourPluginName.dll, but for example also Discord.Net.dll if you decided to depend on it, as ASF doesn't include it itself. Bundling libraries that are shared with ASF can still make sense if you want to ensure API compatibility (e.g. being sure that Newtonsoft.Json which you depend on in your plugin will always be in version X and not the one that ASF ships with), but obviously doing that comes for a price of increased memory/size and worse performance, and therefore should be carefully evaluated.

If you know that the dependency which you need is included in ASF, you can mark it with IncludeAssets="compile" as we showed you in the example csproj above. This will tell the compiler to avoid publishing referenced library itself, as ASF already includes that one. Likewise, notice that we reference the ASF project with ExcludeAssets="all" Private="false" which works in a very similar way - telling the compiler to not produce any ASF files (as the user already has them). This applies only when referencing ASF project, since if you reference a dll library, then you're not producing ASF files as part of your plugin.

Если из-за вышесказанного вы запутались, и не знаете что делать, проверьте, какие dll-библиотеки включены в пакете ASF-generic.zip, и убедитесь что ваш плагин включает в себя только те библиотеки, которых там нет. В случае самых простых плагинов это будет только YourPluginName.dll. Если у вас при выполнении возникнут проблемы с какими-то библиотеками, включите в пакет также эти библиотеки. Если ничего не работает - вы всегда можете решить добавить в пакет вообще все зависимости.


Платформо-специфичные зависимости

Платформо-специфичные зависимости создаются как часть сборок для конкретных ОС, поскольку на целевой машине отсутствует среда исполнения .NET Core, и ASF работает через собственную среду исполнения .NET Core, включенную в состав сборки под данную ОС. С целью минимизировать размер сборки, ASF урезает все платформо-специфичные зависимости, чтобы они включали в себя только тот код, которому может реально быть передано управление в процессе работы программы, что по сути отрезает все неиспользуемые части среды исполнения. This can create a potential problem for you in regards to your plugin, if suddenly you find out yourself in a situation where your plugin depends on some .NET Core feature that isn't being used in ASF, and therefore OS-specific builds can't execute it properly, usually throwing System.MissingMethodException in the process.

Вы никогда не столкнётесь с этой проблемой в универсальной сборкой, потому что они никогда не имеют платформо-специфичных зависимостей (поскольку в этом случае для запуска ASF на целевой машине должна быть работоспособная среда исполнения). Поэтому использование вашего плагина исключительно на универсальных сборках автоматически решает проблему, но очевидным недостатком будет невозможность использовать ваш плагин у пользователей, которые используют сборки ASF под конкретную ОС. Если вы сомневаетесь, что ваша проблема связана с платформо-специфичными зависимостями - вы можете также использовать этот метод для проверки, загрузив ваш плагин в универсальную сборку ASF и посмотрев, решит ли это проблему. If it does, you have plugin dependencies covered, and it's the native dependencies causing issues.

Unfortunately, we had to make a hard choice between publishing whole runtime as part of our OS-specific builds, and deciding to cut it out of unused features, making the build over 50 MB smaller compared to the full one. We've picked the second option, and it's unfortunately impossible for you to include the missing runtime features together with your plugin. If your project requires access to runtime features that are left out, you have to include full .NET runtime that you depend on, and that means running your plugin together with generic ASF flavour. You can't run your plugin in OS-specific builds, as those builds are simply missing a runtime feature that you need, and .NET Core runtime as of now is unable to "merge" native dependency that you could've provided with our own. Perhaps it'll improve one day in the future, but as of now it's not.

ASF's OS-specific builds include the bare minimum of additional functionality which is required to run our official plugins. Apart of that being possible, this also slightly extends the surface to extra dependencies required for the most basic plugins. Therefore not all plugins will need to worry about native dependencies to begin with - only those that go beyond what ASF and our official plugins directly need. This is done as an extra, since if we need to include additional native dependencies ourselves for our own use cases anyway, we can as well ship them directly with ASF, making them available, and therefore easier to cover, also for you.

Clone this wiki locally