Zum Artikel Zum Inhaltsverzeichnis Zur Kapitelnavigation

sOU verwendet Cookies für deine Anmeldung und zum Schutz von Formularen. Es gibt keine Analyse- oder Werbecookies und kein Tracking durch Drittanbieter.

Du kannst direkt fortfahren. Nur wenn du „Hinweis 180 Tage ausblenden“ wählst, speichern wir zusätzlich diese Einstellung in deinem Browser.

Panel-Schema und Aktionen

panel.json, Feldtypen, Werte, Aktionen und Anbindung an das HUD.

Stand: 17. Oktober 2026 · ca. 9 Minuten Lesezeit

Ein HUD definiert seine Bedienfelder in wwwroot/panel.json. sOU erzeugt daraus den Panel-Editor. Texte, Schalter, Medien und Referenzen werden als Einstellungen gespeichert; Aktionsbuttons senden dagegen einmalige Nachrichten. Das HUD legt selbst fest, wie ein Feld seine Darstellung beeinflusst.

Dieses Kapitel richtet sich an HUD-Autoren. Die Bedienung fertiger Panels steht unter HUD-Panels verwenden. Die Paketregeln sind unter HUD-Paketformat beschrieben.

Dein erstes Bedienfeld

Die SDK-Vorlagen enthalten bereits das Textfeld „Überschrift“. Probiere zunächst dieses Feld aus: Beispiel installieren, Panel öffnen, Text ändern und speichern. Die Ausgabe übernimmt den gespeicherten Text. Danach kannst du ein eigenes Feld ergänzen.

  1. In wwwroot/panel.json einen Abschnitt und ein Feld anlegen. Im folgenden vollständigen Beispiel ist der Abschnitt display, das Textfeld caption.
  2. Im HUD den Panelstream abonnieren. In der Webvorlage wird der Text aus message.state.values.display?.caption gelesen; in C# liefert state.Text("display", "caption") den Wert. Die Webvorlage und die Blazorvorlage enthalten die Verbindung bereits.
  3. Den Text an ein HTML-Element beziehungsweise eine Razor-Ausgabe binden. Solange kein Text gespeichert wurde, eine eigene Standardüberschrift anzeigen. Bei HTML textContent verwenden.
  4. Eine neue Paketversion bauen und importieren, Ausgabe neu laden, Panel öffnen und den Text speichern. Erst das Zusammenspiel von Definition, Empfang und Darstellung macht das Feld nutzbar.

Verwende für dauerhafte Einstellungen normale Felder. Für „Animation jetzt starten“ ist ein Aktionsbutton geeignet: Er löst einen einmaligen Vorgang aus und wird nach einer Wiederverbindung nicht nachgeholt. Die nachfolgenden Abschnitte beschreiben alle Feldtypen und Nachrichten vollständig.

Definition und Grenzen

Die Wurzel ist ein JSON-Array aus Abschnitten. Ein Abschnitt besitzt name, label und inputs. Ein Feld besitzt type, name, label und optional values. Eine nicht vorhandene Paneldatei ergibt kein Panel; eine ungültige vorhandene Datei verhindert die Installation.

ElementTypGrenze
Gesamte DateiUTF-8-JSON-ArrayHöchstens 64 KiB.
AbschnitteArrayHöchstens 16.
name eines Abschnitts/FeldsString1–64 ASCII-Zeichen; beginnt mit Buchstaben, danach Buchstaben, Ziffern, Unterstriche oder Bindestriche. Muster ^[a-zA-Z][a-zA-Z0-9_-]{0,63}$.
labelString1–160 Zeichen; sichtbare verständliche Beschriftung.
inputsArrayErforderlich, höchstens 64 Felder pro Abschnitt.
typeString-EnumEin unterstützter Feldtyp; numerische Werte oder unbekannte Typen sind ungültig.
valuesArray oder nullHöchstens 64 Auswahlwerte. Bei select ist mindestens einer erforderlich.
values[].nameString1–160 Zeichen ohne Steuerzeichen. Ein Datenwert, keine Feldkennung: etwa 2.5em ist erlaubt.
values[].labelString1–160 Zeichen; Beschriftung der Auswahl oder des Aktionsbuttons.

Abschnittsnamen müssen in der Datei eindeutig sein, Feldnamen innerhalb ihres Abschnitts und Auswahlwerte innerhalb ihres Felds. Diese Kennungen werden ordinal unterschieden. Verwende dauerhaft stabile, konsistent geschriebene Namen: Sie sind Schlüssel gespeicherter Werte und der Update-Übernahme. Ein geändertes label ändert die sichtbare Beschriftung; ein geändertes name erzeugt aus Sicht der Übernahme ein anderes Feld.

Vollständiges Beispiel

[
  {
    "name": "display",
    "label": "Darstellung",
    "inputs": [
      { "type": "text", "name": "caption", "label": "Überschrift" },
      { "type": "checkbox", "name": "show_caption", "label": "Überschrift anzeigen" },
      {
        "type": "select", "name": "scale", "label": "Schriftgröße",
        "values": [
          { "name": "2em", "label": "Normal" },
          { "name": "2.5em", "label": "Groß" }
        ]
      },
      { "type": "player", "name": "featured_player", "label": "Spieler" },
      { "type": "team", "name": "featured_team", "label": "Team" },
      { "type": "match", "name": "featured_match", "label": "Match" },
      { "type": "image", "name": "logo", "label": "Logo" },
      { "type": "images", "name": "sponsors", "label": "Sponsorenbilder" },
      {
        "type": "action", "name": "cue", "label": "Einblendung",
        "values": [
          { "name": "show", "label": "Einblenden" },
          { "name": "hide", "label": "Ausblenden" }
        ]
      },
      { "type": "action", "name": "restart_animation", "label": "Animation neu starten" }
    ]
  }
]

Das Beispiel beschreibt nur die Bedienelemente. Ohne entsprechende Auswertung im HUD blendet ein Button nichts ein und ändert ein Größenfeld keine Schrift. Verknüpfe ausschließlich die Felder, die deine Anwendung tatsächlich unterstützt.

Feldtypen und gespeicherte Werte

TypWert im ZustandStandard und Validierung
textStringStandard ""; höchstens 4.096 Zeichen.
checkboxBooleanStandard false. Strings wie "true" und Zahlen sind keine gültigen Ersatzwerte.
selectStringStandard ""; anschließend leer oder exakt einer der deklarierten values[].name-Werte.
playerStringSteam-ID des gewählten verwalteten Spielers; leer bei keiner Auswahl. Aufgelöste Metadaten stehen separat in references.
teamStringVerwaltete Team-ID oder leer; keine CT-/T-Seite.
matchStringVerwaltete Match-ID oder leer; die Auswahl aktiviert nicht selbst ein Match.
imageStringLeerer String oder auflösbarer lokaler Pfad unter /cast-media/. Keine freie externe Bild-URL.
imagesArray aus StringsStandard []; höchstens 16 Einträge. Jeder Eintrag muss als lokale Bildreferenz gültig sein.
actionKein gespeicherter FeldwertMit values ein Button je deklarierter Aktion; ohne Auswahlwerte ein Button mit value: null.

Es gibt im aktuellen Schema keinen eigenen Zahlen-, Farb-, Slider-, Pflichtfeld- oder frei konfigurierbaren Standardwerttyp. Benötigt dein HUD beispielsweise eine Farbe als Text, muss es diesen Text selbst validieren und bei ungültiger Eingabe einen passenden Fallback verwenden. Ein zusätzliches default-Feld im JSON stellt keinen vereinbarten Standardwert her.

Die Spielerauswahl bezieht sich auf die lokale Bibliothek. Ein spezielles Schemaattribut für „nur aktuell lebende Spieler“ oder „nur aktuelle Live-Spieler“ gehört nicht zum Vertrag. Referenzen und Texte sind auf höchstens 4.096 Zeichen begrenzt; die eigentliche Identität muss trotzdem aus den angebotenen Verwaltungsdaten stammen.

Bilder und Medien

Der Panel-Editor importiert PNG- und JPEG-Bilder bis 4 MiB pro Datei in die gemeinsame Medienablage. Der Zustand enthält den lokalen Pfad, nicht die vollständigen Bildbytes. Verwende im nativen SDK hud.media(path) beziehungsweise hud.Media(path), um diesen Pfad gegen den Host aufzulösen. Die Bilder werden mit der HUD-Browsersitzung geladen.

Beim Entfernen einer Bildreferenz aus dem Panel wird eine möglicherweise anderweitig verwendete Mediendatei nicht automatisch gelöscht. Eine Datei direkt aus dem Paket ist dagegen ein statisches Asset und wird relativ zur Paketbasis geladen. Diese beiden Arten von Bildern nicht verwechseln.

Der Medienbestand kann auch Dateien anderer Verwaltungsbereiche enthalten; die Möglichkeiten eines dortigen Editors sind keine Erweiterung des Panel-Dateidialogs. Für die LHM-Ausgabe übersetzt der Host die benötigten Bildwerte und bietet zusätzlich die entsprechenden Legacy-Bildrouten an.

Paneltransport

Native HUDs abonnieren SignalR unter /hud-live/panels und rufen die Streammethode Watch(hudId, version) auf. Der SDK-Client übernimmt die Argumente aus der geladenen Paketadresse. Die lokale Browsersitzung, Loopback- und Originprüfung gelten wie beim Livestream. Browser können hier weder Werte speichern noch Aktionen auslösen.

Nachricht/FeldTypBedeutung
hudIdStringHUD-Kennung der Nachricht.
versionStringPaketversion der Nachricht.
stateHudPanelState oder nullVollständiger wiederholbar anwendbarer Einstellungsstand.
actionHudPanelAction oder nullEinmaliger Befehl für jetzt verbundene Ausgaben.
state.revision64-Bit-GanzzahlRevision des gespeicherten Stands; 0 steht für noch ungespeicherte Standards.
state.valuesObjekt nach Abschnitt und FeldTypisierte JSON-Werte der definierten Einstellungsfelder. Keine Aktionswerte.
state.referencesObjekt nach Abschnitt und FeldSeparat aufgelöste Player-/Team-/Matchreferenzen.
action.idUUID-StringEindeutige Kennung dieser Auslösung.
action.section, action.nameStringsAbschnitts- und Feldkennung des Aktionsfelds.
action.valueString oder nullAusgewählter deklarierter Aktionswert; ohne Auswahlwerte null.

Beispiel eines Zustands

{
  "hudId": "mein-cast-hud",
  "version": "1.2.0",
  "state": {
    "revision": 3,
    "values": {
      "display": {
        "caption": "Finale",
        "show_caption": true,
        "scale": "2em",
        "featured_player": "",
        "featured_team": "team-a",
        "featured_match": "",
        "logo": "",
        "sponsors": []
      }
    },
    "references": {
      "display": {
        "featured_team": {
          "id": "team-a",
          "name": "Team A",
          "image": null,
          "teamId": null,
          "missing": false
        }
      }
    }
  },
  "action": null
}

Bei einer Spielerreferenz kann teamId deren verwaltetes Team enthalten; bei Team und Match bleibt dieses Feld null. image ist das vorhandene Avatar- oder Logobild, sonst null. Wird das referenzierte Objekt später entfernt, bleibt dessen id erhalten und missing wird true; Name und Bild können dann fehlen. Erfinde keinen Ersatzdatensatz.

Bibliotheksänderungen können aktualisierte Referenzen auslösen, ohne eine neue GSI-Nachricht und ohne eine neue Speicherrevision der Panelwerte. Deshalb Nachrichten mit gleicher state.revision nicht pauschal verwerfen: Die aufgelösten Namen oder Bilder können sich geändert haben.

Beispiel einer Aktion

{
  "hudId": "mein-cast-hud",
  "version": "1.2.0",
  "state": null,
  "action": {
    "id": "00000000-0000-4000-8000-000000000001",
    "section": "display",
    "name": "cue",
    "value": "show"
  }
}

Diese UUID ist ausschließlich ein Beispiel. Jede tatsächliche Auslösung erhält eine neue Kennung. Prüfe Abschnitt, Name und Wert, bevor dein HUD reagiert. Die Aktion „Einblenden“ nicht aus einem gespeicherten Zustand rekonstruieren und nach Reconnect nicht selbst wiederholen.

Speichern, Konflikte und Wiederverbindung

Änderungen im Panel-Editor werden erst mit Speichern und anwenden an das HUD übertragen. Die Aktion prüft und speichert alle Abschnitte zusammen, erhöht die Revision und verteilt den neuen Zustand an die verbundenen Ausgaben derselben Paketversion. Bei zwischenzeitlichen Änderungen wird der ältere Stand nicht über den neueren gespeichert. Ein Tabwechsel ist keine Speicherung.

Aktionsbuttons wirken sofort und unabhängig von ungespeicherten Formularwerten. Soll eine Aktion die gerade geänderten Einstellungen verwenden, müssen diese zuerst gespeichert werden. Eine Aktion ohne verbundenen Empfänger wird nicht für später vorgemerkt. Eine Versandbestätigung ist keine Rückmeldung des HUDs, dass die sichtbare Animation abgeschlossen ist.

Jedes neue Abonnement erhält den vollständigen aktuellen Zustand und danach neue Nachrichten. Frühere Aktionen werden nicht nachgeliefert. Verarbeite Nachrichten zügig: Bei mehr als 64 wartenden Nachrichten wird das Abonnement beendet. Der SDK-Client verbindet sich anschließend erneut und erhält den aktuellen Zustand. Eine Exactly-once-Garantie für Aktionen gibt es nicht; behandle jede Aktions-ID höchstens einmal und rechne bei einer unterbrochenen Verbindung mit verpassten Aktionen.

Alle Browser-, OBS- und Overlayausgaben derselben HUD-ID und Paketversion teilen den Panelstand. Eine gezielte Auswahl einer einzelnen Ausgabeinstanz ist nicht Teil des Vertrags. Andere HUD-IDs und andere Versionen erhalten die Nachricht nicht; das ist eine fachliche Zuordnung innerhalb derselben lokalen Origin, keine Sandbox.

Panelwerte bei HUD-Updates

  1. Existiert für die neue Paketversion bereits eine gespeicherte Konfiguration, bleibt diese erhalten, auch wenn sie bewusst leere Werte enthält.
  2. Andernfalls sucht sOU beim ersten Panelzugriff die numerisch neueste ältere installierte Version derselben ID mit gespeicherten Werten.
  3. Nur Felder mit identischer Abschnittskennung, Feldkennung und identischem Typ werden übernommen.
  4. Jeder Wert wird gegen das neue Schema geprüft. Nicht mehr erlaubte Auswahlwerte, entfernte Bilder oder geänderte Typen fallen für dieses Feld auf den gültigen Standard zurück.
  5. Der übernommene Zielstand wird mit Revision 1 gespeichert und ist danach unabhängig von der älteren Version. Aktionen werden weder übernommen noch ausgelöst.

Neue Felder starten mit leeren Strings, false oder leerer Bildliste. Entfernte Felder verschwinden nur im neuen Stand. Es werden keine Umbenennungen geraten, keine Werte aus anderen HUD-IDs übernommen und keine neuere Konfiguration in ein Downgrade zurückkopiert. Die Quelle muss noch installiert sein, weil ihr Schema zum Typvergleich benötigt wird. Beschädigte Quellkonfigurationen sind ein Fehler und werden nicht unbemerkt überschrieben.

Prüfung für Autoren

  • Jedes sichtbare Feld im HUD auswerten oder aus der Definition entfernen.
  • Leere Standardwerte und revision: 0 ausdrücklich behandeln.
  • Referenzauflösung mit fehlenden Objekten und Bildern prüfen.
  • Speichern und sofortige Aktion getrennt testen, einschließlich ungespeicherter Eingaben.
  • Nach Browser-Neuladen denselben Zustand erhalten, ohne eine vergangene Aktion erneut auszuführen.
  • Update mit unveränderten und geänderten Feldtypen sowie laufender älterer Ausgabe prüfen.

Die konkreten Clientmethoden und Beispiele findest du unter JavaScript-Client und C#-Client.

Zum Seitenanfang