Skip to content

Plugins pt BR

GitHub Action edited this page Dec 28, 2020 · 45 revisions

Plugins

À partir do ASF V4, o programa inclui suporte para plugins customizados que podem ser carregados durante a execução. Plugins permitem que você personalize o comportamento do ASF, adicionando comandos e lógicas de troca personalizados ou mesmo uma completa integração com serviços de terceiros e APIs.


Para usuários

O ASF carrega os plugins localizados na pasta plugins, dentro da pasta do ASF. Uma prática recomendada é criar uma pasta para cada plugin que você queira usar, que pode ser baseada no nome do plugin, tal como MyPlugin. A estrutura então será plugins/MyPlugin. Todos os arquivos binários do plugin devem ser colocados dentro dessa pasta, o ASF vai carregar e usar seu plugin corretamente após reiniciar.

Geralmente os desenvolvedores publicarão seus plugins em um arquivo zip com uma estrutura determinada, então basta descompactar o arquivo zip na pasta plugins, que criará a pasta apropriada automaticamente.

Se o plugin foi carregado com êxito, você verá seu nome e versão no log. Você deve consultar os desenvolvedores dos plugins em caso de dúvidas, problemas ou forma de uso relacionado com os plugins que você decidiu usar.

Você pode encontrar alguns plugins em destaque na seção terceiros.

Por favor, note que alguns plugins podem ser mal intencionados. Você deve sempre usar apenas plugins de desenvolvedores confiáveis. Os desenvolvedores do ASF não podem garantir os benefícios padrões do ASF (tal como a não presença de malwares ou ser livre de VAC ban) caso você decida usar qualquer plugin personalizado. Também não podemos oferecer suporte a configurações que utilizam esses plugins, já que você não estará mais rodando a versão original do código do ASF.


Para desenvolvedores

Plugins são bibliotecas padrão .NET que herdam a interface IPlugin em comum com o ASF. Você pode desenvolver plugins inteiramente independentes da linha principal do ASF e reutilizá-los nas suas versões atuais e futuras, contando que a API permaneça compatível. O sistema de plugins usado no ASF é baseado em System.Composition, conhecido anteriormente como Managed Extensibility Framework que permite que o ASF descubra e carregue suas bibliotecas durante o tempo de execução.


Como começar

Seu projeto deve ser uma biblioteca padrão .NET que vise o framework da sua versão alvo do ASF, como especificado em compilação. Recomendamos que você busque o .NET Core, mas plugins .NET Framework também são aceitos.

O projeto deve fazer referência a arquitetura principal ArchiSteamFarm, a biblioteca pré-compilada ArchiSteamFarm.dll que você baixou como parte do lançamento, ou o projeto fonte (por exemplo, se você decidiu adicionar a árvore do ASF como submódulo). Isso permitirá que você acesse e descubra as estruturas do ASF, seus métodos e propriedades, especialmente a interface núcleo do IPlugin que você precisará herdar para o próximo passo. O projeto deve também fazer referência, no mínimo, ao System.Composition.AttributedModel, que permite que você use o [Export] para exportar seu IPlugin para ser usado no ASF. Além disso, você pode querer/precisar fazer referência a outras bibliotecas comuns a fim de interpretar as estruturas de dados que são dadas a você em algumas interfaces, mas a menos que você realmente precise delas, isso é suficiente por enquanto.

Se você fez tudo certo, seu csproj será semelhante ao exemplo abaixo:

<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:\\Caminho\Para\Pasta\Onde\Esta\O\ArchiSteamFarm.dll" />

    <!-- Caso esteja compilando como parte da árvore raís do ASF, use isso ao invés da <Reference> acima -->
    <!-- <ProjectReference Include="C:\\Caminho\Para\ArchiSteamFarm\ArchiSteamFarm.csproj" ExcludeAssets="all" Private="false" /> -->
  </ItemGroup>
</Project>

Da parte do código, sua classe de plugin deve herdar da interface IPlugin (seja explicitamente ou implicitamente herdando de uma interface mais especializada, tal como IASF) e [Export(typeof(IPlugin))] para que seja reconhecido pelo ASF durante o tempo de execução. E exemplo mais puro disso seria:

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");
        }
    }
}

Para utilizar seu plugin você deve primeiro compila-lo. Você pode fazer isso pela sua IDE, ou de dentro da pasta raiz do seu projeto através do comando:

# Se o seu projeto for independente (não é preciso definir um nome já que ele será único)
dotnet publish -c "Release" -o "out"


# Se o seu projeto fizer parte da árvore de código do ASF (para evitar a compilação de partes desnecessárias)
dotnet publish YourPluginName -c "Release" -o "out"

Após isso seu plugin estará pronto. Como exatamente você quer distribuir e publicar seu plugin é por sua conta, mas recomendamos criar um arquivo zip com uma pasta apenas, chamada YourNamespace.YourPluginName, dentro da qual você colocará seu plugin compilado juntamente com suas [dependências](#dependências -do-plugin). Dessa forma o usuário precisará apenas descompactar o arquivo zip dentro da pasta plugins e nada mais.

Esse é o cenário mais básico, apenas para começar. Temos o projeto ExamplePlugin que mostra interfaces e ações que você pode fazer dentro do seu próprio plugin, incluindo comentários úteis. Sinta-se livre para dar uma olhada se você quiser aprender com um código funcional, ou explore o namespace ArquiSteamFarm.Plugins por sua conta e consulte a documentação incluída para todas as opções disponíveis.


Disponibilidade de API

O ASF, além do que você tem acesso pela interface, expõe muito de suas APIs internas, as quais você pode usar para estender sua funcionalidade. Por exemplo, se você quiser enviar algum tipo de novo pedido para o Steam web você não precisa implementar tudo a partir do zero, tratando todos os problemas com os quais tivemos de lidar antes de você. Simplesmente use nosso Bot.ArchiWebHandler que já expõe muitos métodos UrlWithSession() para você usar, cuidando de todas as coisas de baixo nível como autenticação, atualização da sessão ou limitação de tráfego para você. Da mesma forma, para enviar pedidos web fora da plataforma Steam, você pode usar a classe padrão .NET HttpClient, mas é melhor usar Bot.ArchiWebHandler.WebBrowser que está disponível, o que mais uma vez lhe oferece uma ajuda, por exemplo, no que diz respeito a tentar novamente pedidos falhos.

Temos uma política muito aberta em questão da disponibilidade da nossa API, então se você quiser usar algo já incluso no código do ASF basta abrir um chamado e explicar nele o uso planejado da API interna do ASF. É muito provável que não tenhamos nada contra, desde que o seu uso preterido faça sentido. É simplesmente impossível abrirmos tudo o que alguém gostaria de usar, então abrimos o que mais faz sentido para nós e esperamos por pedidos caso haja necessidade de acesso a algo que não é público ainda. Isso inclui as sugestões a respeito nas novas interfaces IPlugin que podem fazer sentido de serem adicionadas para estender funcionalidades existentes.

Na verdade, a API interna do ASF é a única limitação real quanto ao que seu plugin pode fazer. Nada te impede de, por exemplo, incluir a biblioteca Discord.Net no seu aplicativo e criar uma ponte entre seu bot do Discord e os comandos do ASF, pois seu plugin também pode ter dependências próprias. As possibilidades são infinitas, e nós fizemos o possível para dar o máximo de liberdade e flexibilidade possível para seu plugin, então não há limites artificiais em nada, apenas não temos completamente certeza de quais partes do ASF são cruciais para o desenvolvimento do seu plugin (que você pode resolver ao nos informar, e mesmo sem isso você pode sempre reimplementar a parte que você necessita).


Compatibilidade de API

É importante salientar que o ASF é um aplicativo de consumo e não uma biblioteca típica com superfície de API fixa da qual você pode depender incondicionalmente. Isso significa que você não pode supor que seu plugin, uma vez compilado, continuará funcionando em todas as futuras versões do ASF, é simplesmente impossível se você quiser continuar a desenvolver o programa, e ser incapaz de se adaptar a mudanças constantes do Steam em nome da compatibilidade retrospectiva não é apropriado para nosso caso. Isto deve ser lógico para você, mas é importante salientar esse fato.

Faremos o nosso melhor para manter partes públicas do ASF funcionais e estáveis, mas não teremos medo de quebrar a compatibilidade se surgirem boas razões suficientes, seguindo nossa política de depreciação nesse processo. Isto é especialmente importante no que diz respeito às estruturas internas da ASF que são expostas a você como parte da infra-estrutura do ASF, explicadas acima (por exemplo, ArchiWebHandler) que podem ser melhoradas (e, portanto, reescritas) como parte de aprimoramentos do ASF em versões futuras. Faremos o possível para informá-lo adequadamente nos logs de alterações e incluir avisos apropriados durante o tempo de execução sobre recursos obsoletos. Não temos intenção de reescrever tudo sem que haja uma necessidade realmente grande, então você pode ter certeza de que a próxima versão menor do ASF não vai simplesmente destruir seu plugin completamente apenas porque ela tem um número de versão maior, mas ficar de olho nos logs de atualização e verificar ocasionalmente se tudo está funcionando bem é uma boa ideia.


Dependências de plugin

Seu plugin incluirá pelo menos duas dependências por padrão, referência para a API interna ArchiSteamFarm e PackageReference de System.Composition.AttributedMode que é necessário para ser reconhecido como um plugin do ASF. Além disso, mais dependências podem ser inclusas dependendo do que você decidiu fazer no seu plugin (por exemplo, a biblioteca Discord.Net caso você decidir integrar com o 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. Retirar as dependências compiladas que são compartilhadas com o ASF não é um requisito absoluto para que seu plugin funcione, mas fazer isso irá reduzir drasticamente a quantidade de memória utilizada e o tamanho do seu plugin, além de melhorar o desempenho, devido ao fato de que o ASF compartilhará suas dependências e só carregará as bibliotecas que ele não conhece.

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.

Se você tiver dúvidas em relação ao que foi dito acima e você não tem idéias melhores, verifique quais bibliotecas dll estão inclusas no pacote ASF-generic.zip e certifique-se que seu plugin inclua apenas as que não fazem parte desse pacote. Para a maioria dos plugins mais simples isso incluirá apenas NomeDoSeuPlugin.dll. Se você tiver algum problema durante o tempo de execução em relação a algumas bibliotecas, inclua também as bibliotecas afetadas. Se todo o resto falhar, você pode sempre decidir agrupar tudo.


Dependências nativas

Dependências nativas são geradas como parte de compilações específicas para Sistemas Operacionais, pois não há o tempo de execução .NET Core disponível no host e o ASF estará rodando através de seu próprio tempo de execução .NET Core que é agrupado como parte da compilação específica para SO. Para minimizar o tamanho da compilação, o ASF corta suas dependências nativas para incluir apenas o código que pode ser alcançado dentro do programa, o que efetivamente reduz as partes não utilizadas do tempo de execução. 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 or System.Reflection.ReflectionTypeLoadException in the process.

Isto nunca será um problema com as compilações genéricas, pois elas nunca lidam com dependências nativas (pois elas têm um tempo de execução completo no host, executando o ASF). Essa também é uma solução automática para o problema: use seu plugin exclusivamente em compilações genéricas, mas obviamente isso tem seu lado ruim, o de privar usuários que rodem compilações específicas para SO de usarem seu plugin no ASF. Se você estiver se perguntando se seu problema está relacionado a dependências nativas, você pode usar este método para verificação, carregue seu plugin em uma compilação genérica do ASF e veja se ele funciona. 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 simply not possible.

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