C# mit IntelliSense in VS Code entwickeln
Der eingebaute C#-Editor von Streamer.bot reicht für kurze Snippets, aber sobald eine Action größer wird, fehlt das Wichtigste: Autovervollständigung, Typprüfung und das Abfangen von Tippfehlern vor dem Speichern. Die Lösung ist ein kleines lokales Projekt, das gegen dieselben DLLs referenziert, die Streamer.bot intern lädt. Dann schreibst du in VS Code mit voller IntelliSense und kopierst die fertige Datei zurück in die Execute C# Code-Sub-Action.
Der Trick dabei: lokal muss deine Klasse von CPHInlineBase erben, damit der Compiler das CPH-Objekt kennt. In Streamer.bot heißt die Klasse CPHInline und erbt nicht explizit, weil SB die Verbindung zur API selbst herstellt. Ein Preprocessor-Guard hält beide Fälle in einer Datei, sodass du dieselbe Datei kopieren kannst, ohne vorher etwas herauszuschneiden.
Doku: docs.streamer.bot · Visual Studio Code
Warum ein externer Editor
Abschnitt betitelt „Warum ein externer Editor“In der SB-Action selbst gibt es keine Symbol-Datenbank: CPH. löst keine Vorschlagsliste aus, Generics wie GetGlobalVar<int> werden nicht geprüft, und ein vergessenes Semikolon merkst du erst beim Compile-Versuch. Mit einem lokalen .csproj, das die Streamer.bot-Assemblies referenziert, bekommst du:
- IntelliSense für das komplette
CPH-Objekt und alle .NET-Typen - Fehler vor dem Einfügen: Tippfehler, falsche Typargumente, fehlende Usings rot unterstrichen
- Refactoring und Navigation: Umbenennen, Go-to-Definition, Quick-Fixes
Der lokale Build muss nicht laufen oder gestartet werden. Es geht nur darum, dass Roslyn, die Sprach-Engine hinter VS Code, deinen Code gegen die echten DLLs analysiert.
Das csproj anlegen
Abschnitt betitelt „Das csproj anlegen“Lege einen Ordner an, öffne ihn in VS Code mit der offiziellen C# Extension von Microsoft (ms-dotnettools.csharp) und erstelle eine Datei Sb.csproj. Wichtig sind das Target-Framework net481 (Streamer.bot läuft auf .NET Framework 4.8.1) und die Konstante EXTERNAL_EDITOR, die den Guard im Code aktiviert.
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net481</TargetFramework> <LangVersion>13.0</LangVersion> <Nullable>enable</Nullable> <UseWPF>true</UseWPF> <DefineConstants>EXTERNAL_EDITOR</DefineConstants> <NoWarn>CS0114</NoWarn> <StreamerBotPath>C:/Tools/streamer.bot</StreamerBotPath> </PropertyGroup>
<ItemGroup> <Reference Include="$(StreamerBotPath)/Streamer.bot.Plugin.Interface.dll" /> <Reference Include="$(StreamerBotPath)/Streamer.bot.Common.dll" /> <Reference Include="$(StreamerBotPath)/Twitch.Common.dll" /> <Reference Include="$(StreamerBotPath)/NAudio*.dll" /> <Reference Include="$(StreamerBotPath)/Wpf*.dll" /> <Reference Include="$(StreamerBotPath)/Newtonsoft.Json.dll" /> <Reference Include="$(StreamerBotPath)/System.*.dll" /> <Reference Include="System.Web" /> <Reference Include="System.Net.Http" /> </ItemGroup></Project>Setze StreamerBotPath auf deinen tatsächlichen Streamer.bot-Installationsordner, also das Verzeichnis mit der Streamer.bot.exe und den DLLs daneben. Newtonsoft.Json.dll ist hier referenziert, deshalb funktioniert JsonConvert und JObject.Parse lokal genauso wie in SB, wo Newtonsoft standardmäßig verfügbar ist.
Der #if EXTERNAL_EDITOR-Trick
Abschnitt betitelt „Der #if EXTERNAL_EDITOR-Trick“Jetzt die eigentliche Code-Datei, zum Beispiel MyAction.cs. Der Guard sorgt dafür, dass lokal eine eindeutig benannte Klasse von CPHInlineBase erbt, während in Streamer.bot derselbe Text als schlichte CPHInline-Klasse kompiliert.
using System;using Newtonsoft.Json.Linq;
#if EXTERNAL_EDITORpublic class MyAction : CPHInlineBase#elsepublic class CPHInline#endif{ public bool Execute() { // Ab hier volle IntelliSense: CPH. zeigt alle Methoden CPH.LogInfo("Action gestartet");
if (CPH.TryGetArg("rawInput", out string input)) { CPH.SendMessage($"Eingabe war: {input}"); }
int count = CPH.GetGlobalVar<int>("hugCount", true); CPH.SetGlobalVar("hugCount", count + 1, true);
return true; }}Was passiert hier:
- Lokal ist
EXTERNAL_EDITORdurch das.csprojdefiniert. Der Compiler nimmtpublic class MyAction : CPHInlineBase. WeilCPHInlineBasedasCPH-Objekt bereitstellt, kennt VS Code jede Methode darauf. - In Streamer.bot ist die Konstante nicht gesetzt. SB sieht
public class CPHInlineohne explizite Vererbung und stellt die Verbindung zur API selbst her.
Der Klassenname im #if-Zweig muss eindeutig sein, weil in einem .csproj mit mehreren Dateien jeder Klassenname nur einmal vorkommen darf. Benenne ihn am besten wie die Datei. Die using-Direktiven oben gehören mit in die Datei, der Guard betrifft nur die Klassendeklaration.
Zurückkopieren in Streamer.bot
Abschnitt betitelt „Zurückkopieren in Streamer.bot“Anders als beim reinen Inline-Editor schneidest du hier nichts heraus. Du kopierst die gesamte .cs-Datei inklusive der using-Zeilen, des #if-Blocks und der schließenden } in die Execute C# Code-Sub-Action. Die Preprozessor-Direktiven sorgen dafür, dass der : CPHInlineBase-Zweig in SB inaktiv bleibt: dort gilt der #else-Zweig, also public class CPHInline. Genau deshalb funktioniert dieselbe Datei in beiden Umgebungen, ohne dass du sie umschreibst.
using System;using Newtonsoft.Json.Linq;
#if EXTERNAL_EDITORpublic class MyAction : CPHInlineBase#elsepublic class CPHInline#endif{ public bool Execute() { CPH.LogInfo("Action gestartet");
if (CPH.TryGetArg("rawInput", out string input)) { CPH.SendMessage($"Eingabe war: {input}"); }
int count = CPH.GetGlobalVar<int>("hugCount", true); CPH.SetGlobalVar("hugCount", count + 1, true);
return true; }}Nach dem Einfügen klickst du in SB auf Compile und speicherst mit Save and Compile. Generics verhalten sich nach dem Kopieren identisch: GetGlobalVar<int>, JObject.Parse oder DeserializeObject<T> kompilieren in SB genau dann, wenn sie lokal grün waren. Genau das ist der Sinn der Übung.
Wenn der Compiler eine Meldung wirft, die mit (are you missing an assembly reference?) endet, fehlt SB eine DLL, die dein .csproj lokal automatisch dabeihatte. Streamer.bot bietet dafür den Find Refs-Button, der versucht, die passende Referenz automatisch nachzulegen. Welche DLLs SB von Haus aus referenziert, steht in der C#-Dokumentation.
Workflow im Überblick
Abschnitt betitelt „Workflow im Überblick“- Code in VS Code schreiben, IntelliSense und Fehlerprüfung nutzen, bis alles grün ist.
- Methoden gegen docs.streamer.bot verifizieren. Die DLLs zeigen dir Signaturen, aber Verhalten wie
runImmediatelybeiCPH.RunAction(...)steht nur in der Doku. - Die gesamte
.cs-Datei markieren und in die Execute C# Code-Sub-Action kopieren, mitsamt#if-Block undusing-Zeilen. - In SB Compile klicken. Bei einer Meldung über eine fehlende Assembly-Referenz Find Refs nutzen.
- Mit Save and Compile speichern und die Action testweise auslösen.
Häufige Fallen
Abschnitt betitelt „Häufige Fallen“- Datei nur teilweise kopiert: Lass den
#if-Block und dieusing-Zeilen drin und kopiere die ganze Datei. Die Direktiven blenden denCPHInlineBase-Zweig in SB automatisch aus, da musst du nichts von Hand entfernen. - Falsches Target-Framework: Streamer.bot läuft auf .NET Framework 4.8.1. Stell im
.csprojnet481ein, nichtnet8.0oder ähnliches. Sonst schlägt lokal Code an, der in SB nicht existiert, oder umgekehrt. - Falscher DLL-Pfad: Zeigt
StreamerBotPathnicht auf den echten Installationsordner, findet VS Code die Assemblies nicht und IntelliSense bleibt leer. Der Pfad muss dieStreamer.bot.Plugin.Interface.dlldirekt enthalten. - Namespace-Konflikte: Doppelte Klassennamen über mehrere Dateien im selben
.csprojbrechen den lokalen Build. Benenne jede Klasse im#if-Zweig eindeutig, am besten nach dem Dateinamen. - Lokal grün, in SB rot: Meist fehlt in SB eine DLL-Referenz, die dein
.csprojlokal automatisch hatte. Klick im Compile-Fehler auf Find Refs, dann ergänzt SB die passende Referenz.