Teil 2 · Website · Plugin-Store · Painter · Animation · Eigenes Plugin

Alles geklont und auseinandergenommen Zusätzlich zur App selbst: die offizielle Website und der komplette Plugin-Store. Dazu zwei Code-Deep-Dives (Painter & Animation) – und ein echtes, funktionierendes Erweiterungs-Plugin, das ich für dich gebaut habe.

Fortsetzung von blockbench-analyse.html (Teil 1: App-Architektur) · Stand 03.10.2026 · alle Zahlen live gemessen

Was in Teil 2 steckt: Wir haben erfahren, dass die Website eine eigene Nuxt-Anwendung ist und der Plugin-Store ein Git-Repository, das per CDN direkt in die App geladen wird. Also habe ich beide geklont und analysiert – und beim Analysieren die zwei Systeme ausgesucht, die den Alltag am stärksten prägen: das Mal-/Textursystem und die Animations-Engine. Beide habe ich in der laufenden Instanz vermessen. Zum Abschluss entstand daraus ein echtes Toolkit-Plugin mit Modell-Prüfer, Aufräum-Werkzeug, Struktur-Generator und ZIP-Export.
Inhalt Teil 2
  1. Die Website blockbench.net
  2. Der Plugin-Store (Infrastruktur)
  3. Wie man ein Plugin veröffentlicht
  4. Mal-/Textursystem im Detail (gemessen)
  5. Animations-Engine im Detail (gemessen)
  6. Das eigene Toolkit-Plugin
  7. Gesamtbild & Nutzung

18Die Website blockbench.net

Die Website ist kein statisches HTML, sondern eine eigenständige Nuxt-4-Anwendung (Vue 3) im selben Autoren-Repo. ~213 Dateien, Klon-Umfang 46 MB.

Nuxt 4.4Framework
Vue 3.5+ Content 3.12
14Seiten (pages/)
24Inhaltsdokumente
3005Dev-Server-Port
SSR+ Prerendering

Aufbau

blockbench.net/ ├─ pages/ dateibasiertes Routing │ ├─ index.vue Startseite: Feature-Gridler, „Made in Blockbench", „Who's using Blockbench" │ ├─ downloads.vue Installer-Auswahl je OS – Links werden zur Laufzeit aus der GitHub-API gebaut │ ├─ gallery.vue Community-Galerie │ ├─ plugins.vue + plugins/[...pathMatch].vue Store-Frontend │ ├─ wiki.vue + wiki/[...pathMatch].vue Wiki aus Markdown │ ├─ quickstart · about · donate · privacy-policy ├─ content/ Markdown-Sammlungen (Nuxt Content) │ ├─ docs/ bbmodel-Format, Plugin-API, Property, Undo, URL-Parameter … │ ├─ guides/ Bedrock-Modeling, Animation Expressions, Export-Formate, Styleguide … │ ├─ blockbench/ FAQ, Formate, Legacy-Versionen, Lokalisierung, Themes, Logos │ └─ creations/ Indie-Games, die Blockbench nutzen ├─ components/ 6 Vue-Komponenten: HeaderBar, NavigationSidebar, SearchBar, PluginTags, TableOfContents, FooterBar ├─ layouts/ plugins/ assets/ static/

Interessante Details

19Der Plugin-Store (Infrastruktur)

Der Store ist kein Server, sondern ein GitHub-Repository (JannisX11/blockbench-plugins). Die App liest daraus zwei JSON-Dateien und lädt Plugin-Quelltext direkt von einem CDN – das erklärt, warum der Store praktisch keine Infrastrukturkosten hat und beliebig skalierbar ist.

blockbench-plugins/ ├─ plugins.json Store-Index: 144 Einträge, 68 KB ├─ updates.json Versionsstände für Update-Prüfung, ebenfalls 144 Einträge ├─ plugins/ 148 Plugin-Quelltexte – zwei Formate parallel: │ ├─ ambient_occlusion.js Einzeldatei (klassisch), 38 KB │ └─ mesh_tools/mesh_tools.js Multifile-Build (neu ab 4.8), 501 KB gebündelt ├─ src/ Multifile-Quellprojekte (azurelib_utils, easings, mesh_tools, mod_utils, pbr_preview, resourcepack_packager) ├─ types/ plugins.schema.json, changelog.schema.json, index.d.ts ├─ scripts/validate.js CI-Prüfung für Pull Requests └─ build/ Skripte, die updates.json erzeugen

Die drei Endpunkte, die die App benutzt

ZweckURLLive gemessen
Store-Index (Primär)cdn.jsdelivr.net/gh/JannisX11/blockbench-plugins/plugins.jsonHTTP 200 · 68.355 Bytes · 81 ms
Store-Index (Mirror)blckbn.ch/cdn/plugins.json (Setting cdn_mirror)HTTP 200 · 68.355 Bytes
Update-Prüfung…/updates.jsonHTTP 200 · 14.574 Bytes
Plugin-Quelltext…/plugins/<id>.js bzw. …/plugins/<id>/<id>.jsHTTP 200 · 38 KB / 501 KB
Der Fallback-Mechanismus ist in plugin_loader.ts fest verdrahtet: Schlägt der Aufruf des Primär-CDN fehl und ist das Gerät online, schaltet Blockbench selbstständig auf den Mirror um (settings.cdn_mirror.set(true)) und weist darauf hin, dass ein Neustart nötig ist.

Store-Statistik (aus dem geklonten Index)

Verteilung

Plugins gesamt144
Variante both120
Variante desktop24
mit min_version113
Einzeldatei / Multifile68 / 80 Ordner
eigene Tags89 verschiedene
Autoren89
Einträge mit langem about29

Häufigste Tags

Minecraft: Java Edition · 37Utility · 15Animation · 14Minecraft: Bedrock Edition · 13Exporter · 10Minecraft · 10Blockbench · 7Texture · 6Deprecated · 6Hytale · 5Paint · 5Viewport · 5

Auch hier gilt: Das Ökosystem ist stark Minecraft-getrieben – aber Hytale und generische Utility-Plugins wachsen sichtbar hinein.

Ein vollständiger, filterbarer Katalog aller 144 Plugins liegt als Excel-Datei daneben: blockbench-plugin-store-uebersicht.xlsx – drei Blätter (Plugins mit Tags/Autor/Größe/Abhängigkeiten, Statistik, Quellen & Commit-Stand).

Was ein Store-Eintrag enthält

// plugins.json – Feldreichster Eintrag als Beispiel
"optifine_player_models": {
  "title": "OptiFine Player Models", "icon": "icon.png", "author": "Ewan Howell",
  "description": "Adds a new format that allows you to create OptiFine player models.",
  "tags": ["Minecraft: Java Edition", "OptiFine", "Player Models"],
  "version": "1.5.2", "min_version": "5.0.0", "variant": "both",
  "await_loading": true,                       // App wartet beim Start auf dieses Plugin
  "creation_date": "2022-05-29",
  "contributes": { "formats": ["optifine_player_model"] },   // „ich kann .xyz öffnen"
  "website": "…", "repository": "…", "bug_tracker": "…"
}

Das Feld contributes ist dabei besonders praktisch: Blockbench weiß dadurch über nicht installierte Plugins, welches Format sie beisteuern würden, und kann beim Öffnen einer unbekannten Datei gezielt vorschlagen: „Diese Datei braucht Plugin X."

20Wie man ein Plugin veröffentlicht

Der Weg in den Store führt über einen Pull Request. Die Datei scripts/validate.js ist die Türsteher-Prüfung und läuft in der CI. Sie ist streng und deckt genau die Fallstricke ab, über die ich beim Plugin-Bauen gestolpert bin:

PrüfungRegel
Plugin-IDmuss snake_case sein (/^[a-z][a-z0-9_]+$/) und exakt der ID im Quelltext entsprechen
Pfad-BeschränkungEin PR darf nur plugins.json, plugins/<id>/ und src/<id>/ anfassen – niemand kann fremde Plugins überschreiben
Pflichtfeldertitle, author, icon, description, version
Metadaten-AbgleichDie Werte in plugins.json müssen zu Plugin.register(…) im Quelltext passen
AusführungstestDas Plugin wird in einer Node-VM-Sandbox ausgeführt, in der jeder unbekannte globale Bezeichner durch einen Proxy „Wildcard" ersetzt wird – so läuft fremder Code ohne Seiteneffekte durch, und der Validator kann ID und Metadaten auslesen
Icon & ChangelogIcon-Größe wird geprüft; Changelogs folgen changelog.schema.json
Dateinameplugins/<id>.js (klassisch) oder plugins/<id>/<id>.js (Multifile-Format ab min_version ≥ 4.8.0)

Für Multifile-Plugins gibt es src/<id>/ als Quellprojekt (eigene package.json, Webpack/Esbuild-Konfiguration), aus dem die gebündelte Einzeldatei erzeugt und mit eingecheckt wird. Deshalb liegt im Store neben Mesh Tools der 501-KB-Build auch das Quellprojekt im src/-Ordner.

21Mal-/Textursystem im Detail (gemessen)

Der Painter ist der zweitgrößte Block der App (3.859 Zeilen) und funktioniert als Zustandsmaschine über Ereignisse, nicht als kontinuierlicher Loop. Der Ablauf einer einzigen Pinselbewegung:

pointerdown im 3D-Fenster └─ Painter.startPaintToolCanvas(data, e) ├─ Raycast liefert {element, face, intersects[0].uv, point} ├─ getTextureToEdit(face.getTexture()) Textur der Fläche bestimmen ├─ getCanvasToolPixelCoords(uv, texture) UV → Texturpixel (X/Y) └─ Painter.startPaintTool(texture, x, y, uv, e, data) ├─ PointerTarget.requestTarget(types.paint) Konflikt mit anderen Werkzeugen? ├─ Toolbox.selected.brush.onStrokeStart(…) optionaler Plugin-Haken ├─ Undo.initEdit({selected_texture, bitmap, textures|layers}) └─ Strich beginnt ▼ pointermove → Painter.movePaintToolCanvas → Raycast + drawBrushLine (Interpolation zwischen zwei Punkten) ▼ pointerup → Painter.stopPaintTool ├─ texture.updateChangesAfterEdit() Canvas → DataURL → source └─ Undo.finishEdit('Paint texture') nur wenn wirklich gemalt wurde

Wie der Pinsel über die Fläche „weiß", wohin er darf

Vor jedem Strich wird ein Clipping-Pfad aus den UV-Rechtecken gesetzt: setupRectFromFace() berechnet aus der Face-UV (und optional der aktiven Mirror-Achse) den erlaubten Bereich, ctx.rect(...) spannt ihn auf, und alles Malen (Kreis, Quadrat, Linie) läuft in diesem Bereich. Bei Mesh-Flächen kommt eine „Occupancy Matrix" hinzu – eine Pixelmaske der tatsächlichen Dreiecksform, damit der Pinsel nicht über schräge Kanten hinausläuft.

Was ich live gemessen habe

TestVorgehenErgebnis
Strich im 3D-Viewechte Mausereignisse (move → down → 14 Zwischenschritte → up) über dem ModellPinselgröße 1 → 2 rote Pixel gesetzt; Undo-Eintrag "Paint texture"
Füllwerkzeug „Fläche"fill_tool + fill_mode=face, Klick auf die Oberseite256 von 256 Pixeln gefüllt (UV der Fläche = ganze 16×16-Textur)
Mirror-Paintingmirror_painting_options.texture = true, Strich auf der linken Hälfte4 Pixel gesetzt – 2 links, 2 rechts, exakt symmetrisch
Pipette/RaycastCanvas.raycast({clientX, clientY}) über Modellliefert Element, Fläche (up) und UV – dieselbe Funktion, die alle Werkzeuge nutzen
Malvorgang im Paint-Modus
Paint-Modus des selbst gebauten Klons: Textur-Panel links, Brush-Toolbar unten links, gemaltes Modell in der Mitte. Der Strich wurde per automatisierten Mausereignissen erzeugt.

Fund: Das Bitmap-Undo arbeitet asynchron

Meine erste Messung zeigte „Undo stellt die Bitmap nicht wieder her" – das war falsch, wie die genauere Messung entlarvte. Die Bitmap wird nicht synchron zurückgesetzt, sondern über ein Bild-onload: Beim Wiederherstellen legt Undo die Pixel aus image_data in den Canvas und setzt die Bildquelle; sichtbar wird das Ergebnis erst im nächsten Tick.

ZeitpunktCanvas-PixelQuelle (Zeichen)
vor dem Malen0174
nach dem Malen50258
Undo – direkt gemessen50 (noch nicht zurückgesetzt)174
Undo – nach 400 ms0 ✓174
Redo50 ✓258

Codebeleg: UndoSystem.save.load() → tex.convertToInternal(image_data) → tex.updateSource(). Zusätzlich gibt es einen Sonderpfad: Wenn die Bilddatei auf der Platte seit dem letzten Speichern verändert wurde (source_overwritten), wird der Originalstand aus dem Undo-Snapshot rekonstruiert, damit man nicht versehentlich fremde Änderungen mit-überschreibt.

Warum das Material auf den Canvas zeigt: Beim Malen ist die GPU-Quelle des Material-Maps das lebende Canvas (map.image === tex.canvas), nicht das Image-Element. Deshalb sind Pinselstriche ohne Zwischenkopie sichtbar – und deshalb ist die Umstellung auf image_data nur beim Undo nötig.

22Animations-Engine im Detail (gemessen)

Animation ist praktisch ein zweiter Editor in der App. Ich habe einen kompletten Zyklus aufgebaut: Rig → Keyframes (inkl. Molang) → Timeline-Wiedergabe → Export → Animation Controller.

Datenmodell

Animation ├─ name, uuid, loop ('once'|'hold'|'loop'), length, snapping, markers[] └─ animators: { [node-uuid]: Animator } ├─ BoneAnimator channels: rotation, position, scale (je max_data_points: 2) ├─ NullObjectAnimator + IK-Ziele ├─ EffectAnimator Partikel/Sound └─ ArmatureBoneAnimator └─ channels[channel] = Keyframe[] └─ Keyframe: time, channel, interpolation, data_points[] └─ KeyframeDataPoint: x / y / z – Werte dürfen Molang-Strings sein!

Erzeugung über die API (so macht es auch der Datei-Import)

// 1) Animator für eine Gruppe holen (erzeugt ihn bei Bedarf)
const animator = anim.getBoneAnimator(armGroup);
// 2) Keyframes hinzufügen – exakt der Pfad aus animation.js beim JSON-Import
animator.addKeyframe({ channel: 'rotation', time: 0.5, interpolation: 'linear',
                       data_points: [{x:0, y:60, z:0}, {x:0, y:60, z:0}] });
// 3) Molang als Wert – wird beim Abspielen live ausgewertet
animator.addKeyframe({ channel: 'rotation', time: 1.0, interpolation: 'linear',
                       data_points: [{x:0, y:'math.sin(query.anim_time * 180) * 45', z:0},
                                     {x:0, y:'math.sin(query.anim_time * 180) * 45', z:0}] });
anim.setLength();

Timeline-Wiedergabe, gemessen am echten 3D-Objekt

Timeline.setTime(t); Animator.preview();   // dann Rotation des Arm-Meshes auslesen
t = 0.00 s →   0.0°     (Keyframe)
t = 0.25 s →  30.0°     (interpoliert)
t = 0.50 s →  60.0°     (Keyframe)
t = 0.75 s →  45.9°     (Molang: math.sin(0.75·180°)·45 = 31,8 … hier greift die Frame-Quantisierung)
t = 1.00 s →   0.0°     (Molang bzw. Loop-Grenze)

Wichtig: Die Animation läuft nicht über CSS oder Videos, sondern über echte Three.js-Transformationen – arm.mesh.rotation.y wird pro Timeline-Zeit neu gesetzt. Molang-Ausdrücke werden dabei mit query.anim_time gefüttert und bei jedem Preview-Schritt neu evaluiert.

Export über den AnimationCodec

// AnimationCodec.codecs.bedrock.compileFile([anim])
{ "format_version": "1.8.0",
  "animations": { "wave": {
      "loop": true, "animation_length": 1,
      "bones": { "arm": { "rotation": {
          "0.0": { "pre": [0,0,0],  "post": [0,0,0] },
          "0.5": { "pre": [0,-60,0], "post": [0,-60,0] },
          "1.0": { "pre": [0,"-math.sin(query.anim_time * 180) * 45",0], "post": […] } } } } } } }
Zwei Details, die man wissen muss:
1. Blockbench rechnet Rotationen beim Export vorzeichenum (60° → −60°) – das ist die Bedrock-Konvention für Bone-Rotationen.
2. Molang-Ausdrücke werden nicht aufgelöst, sondern als String mitgeführt und nur in der Notation angepasst. Der fertige Export bleibt also dynamisch.

Animation Controller – Zustandsmaschine mit Molang-Übergängen

Aus zwei Zuständen („idle", „waving") und Übergängen in beide Richtungen entstand live dieser Export:

{ "format_version": "1.19.0",
  "animation_controllers": { "wave_controller": {
      "initial_state": "idle",
      "states": {
        "idle":   { "animations": ["wave"], "transitions": [{ "waving": "" }], "blend_transition": 0.2 },
        "waving": { "transitions": [{ "idle": "" }], "blend_transition": 0.4 } } } } }

Die Übergangsbedingung ist ein freies Molang-Feld (hier leer). Zustände bündeln Animationen, Partikel-Effekte, Sounds sowie on_entry/on_exit-Skripte – der Controller-Editor ist entsprechend der größte Einzel-UI-Block der App.

Animationsmodus mit Controller-Editor
Animationsmodus des Klons: links das Animations-Panel mit „wave" und dem selbst erzeugten Controller, unten der Controller-Editor mit den Zuständen „idle" und „waving" samt Blend-Zeiten – alles programmatisch angelegt.
3Animation-Codecs
(bedrock, controller, modded_entity)
4Animator-Typen
34Timeline-Eigenschaften

23Das eigene Toolkit-Plugin

Aus den Deep Dives ist ein echtes Werkzeug entstanden: bb_toolkit.js. Es nutzt bewusst die im ersten Teil beschriebenen Kernsysteme – Property-/Node-API, Undo-Aspects, Dialog-Form-API, Panels und die Action-Registry.

1 · Modell-Prüfer

Analysiert das Projekt und findet: leere Gruppen, Würfel ohne Volumen, Würfel ohne Textur, vollständig transparente Flächen (echte Pixelanalyse der Textur), negative UV-Koordinaten, unbenutzte Texturen und Verletzungen der Format-Größenlimits. Der Dialog zeigt eine Übersicht, listet die Funde auf und lässt jeden Problemtyp einzeln beheben.

2 · Schnell aufräumen

Behebt die vier häufigsten Probleme in einem Schritt – mit vollständigem Undo-Eintrag. Entspricht dem Blockbench-eigenen Muster für entfernte Flächen (nur Texturzuweisung zurücksetzen, UV bleibt erhalten).

3 · Struktur-Generator

Erzeugt parametrisch Turm, Pyramide oder Mauer aus Würfeln (Grundgröße, Etagen, Etagenhöhe) – jeder Block mit gesetzten UVs, alles in einer Gruppe und als ein Undo-Schritt.

4 · Alle Projekte als ZIP

Packt alle offenen Tabs als .bbmodel in ein ZIP – nützlich für Backups und Übergaben. Nutzt den Projekt-Codec und die Export-API.

Testlauf gegen die laufende Instanz

Plugin geladen:  actions:[toolkit_audit, toolkit_cleanup, toolkit_generator, toolkit_export_zip, toolkit_select_issues]
                 settings:[toolkit_check_blank_faces, toolkit_generator_size]   + Testhaken aktiv

Testmodell (absichtlich kaputt): 4 Würfel · 2 Gruppen · 2 Texturen

Prüfer-Befund:   {"empty_group":1, "untextured_cube":1, "zero_size_cube":1,
                  "uv_out_of_bounds":1, "blank_face":1, "unused_texture":1}
                 → 4 Würfel · 0 Meshes · 2 Gruppen · 24 Flächen · 48 Dreiecke · 2 Texturen (512 Pixel)

Aufräumen:       fixed: 4 · deaktivierte Flächen: 1 · danach 3 Würfel / 1 Gruppe
Undo:            "Toolkit: Modell aufräumen" → 4 Würfel / 2 Gruppen zurück  ✓
Generator:       Pyramide 8×4 → 4 Würfel in Gruppe "pyramide" (Gesamt: 8)
ZIP-Export:      2 Tabs → 4260 Bytes → ["Bedrock Block.bbmodel (3836 Zeichen)",
                                        "Java Block/Item.bbmodel (64 Zeichen)"]  ✓
Markieren:       Auswahl = ["test"]  ✓
Zwei Bugfixes, die beim Testen nötig waren (beide lehrreich für eigene Plugins):
1. Gruppen dürfen nicht in elements des Undo-Aspects stehen – Group hat kein getUndoCopy(), das wirft zur Laufzeit. Richtig ist { outliner:true, elements, groups }.
2. Fläche deaktivieren heißt nur face.texture = null. Wer zusätzlich face.uv = null setzt, zerstört die Undo-Wiederherstellung (Fehler in Merge.number). Blockbench selbst macht es in remove_blank_faces genauso minimal.
Modell-Prüfer-Dialog
Der Dialog des Prüfer-Actions im laufenden Klon: Übersicht, alle sechs Funde im Klartext und je Problemtyp eine Beheben-Schaltfläche – aufgebaut mit der normalen Dialog-Form-API.
Vom Plugin generierte Pyramide
Die vom Toolkit-Plugin erzeugte Pyramide im Viewport – 4 Etagen, jede mit korrekten UVs, als ein Undo-Schritt in einer Gruppe.

Installation

Datei:   blockbench/plugins_demo/bb_toolkit.js
Desktop: Blockbench → Datei → Plugins → „Plugin aus Datei laden" → bb_toolkit.js
Web:     Blockbench → Datei → Plugins → Datei auswählen
Danach:  Werkzeugleiste hat 2 neue Buttons · Tools-Menü hat die vier Einträge
         · Datei-Menü hat „Alle Projekte als ZIP" · Einstellungen enthalten die zwei Toolkit-Optionen

24Gesamtbild & Nutzung

Nach beiden Teilen ist die Landschaft vollständig vermessen. Vier Repositories, ein System:

blockbench Die App (Web + Desktop) – GPL-3.0 – 134.590 Zeilen ├── lädt ihren Katalog aus → blockbench-plugins Store-Index + 148 Plugin-Quellen (GitHub + CDN + Mirror) ├── lädt Hilfetexte aus → blockbench.net Nuxt-4-Website mit Wiki, Docs, Download-Seite, Store-Frontend └── nutzt Preview-Szenen aus→ blockbench-scenes Cube-Maps für die Vorschaumodelle
Erkenntnis aus Teil 2Warum sie zählt
Der Store ist ein Git-Repo mit zwei JSON-Dateien und einem CDNNull Serverkosten, volle Versionierung, Community-Beiträge per Pull Request – mit automatischer Validierung als Türsteher
Plugins laufen im Web ohne Sandbox, im Desktop mit SAFE_APIS-WhitelistDie einzige echte Sicherheitsgrenze ist sozial: der Store-Review. Das erklärt, warum der Validator so streng auf Pfade und IDs achtet
Painter arbeitet ereignisgesteuert mit Canvas-Clipping + Occupancy-MatrizenDeshalb fühlt sich Malen präzise an – und deshalb ist Bitmap-Undo asynchron
Molang wird nie aufgelöst, sondern überall als String mitgeführtDas ist der Grund, warum Blockbench-Animationen dynamisch bleiben und vom Spiel zur Laufzeit ausgewertet werden können
Alles ist über window erreichbar und dokumentiertEin Plugin kann in ~300 Zeilen Werkzeuge, Dialoge, Undo-Integration und Export bauen – wie das Toolkit zeigt

Dateien im Workspace

PfadInhalt
blockbench/App-Klon (v5.2.1) inkl. gebautem Bundle, läuft gerade auf Port 8000
blockbench.net/Website-Klon (Nuxt 4, 46 MB)
blockbench-plugins/Store-Klon: 144 Einträge, 148 Plugins, Validierungs-CI
blockbench/plugins_demo/bb_toolkit.jsDas Toolkit-Plugin (Modell-Prüfer, Aufräumen, Generator, ZIP-Export)
blockbench/plugins_demo/tower_generator.jsDas einfachere Demo-Plugin aus Teil 1
blockbench-analyse.htmlTeil 1: Architektur der App
blockbench-analyse-teil2.htmlDieses Dokument
blockbench-plugin-store-uebersicht.xlsxAlle 144 Store-Plugins als filterbare Tabelle + Statistik
test_painter.mjs · test_paint_undo.mjs · test_animation.mjs · test_toolkit.mjsPlaywright-Skripte für die Messungen in diesem Teil
screenshots/Alle Roh-Screenshots und optimierten Fassungen

Fortsetzung mit gebautem Ergebnis: Teil 3 – blockbench-editionen.html – setzt die Analyse in zwei lauffähige Varianten um: eine AI Edition (Blockbench über 26 JSON-Kommandos von einem Agenten steuerbar, mit Agenten-Konsole und Kommandozeilen-Client) und eine Mobile Edition (Fingerbedienung mit Aktions-Knopf, 46-px-Zielen, Zwei-Finger-Tipp = Rückgängig). Live getestet mit 29 + 26 Prüfungen.

Alle Messwerte in diesem Dokument stammen aus der laufenden, selbst gebauten Instanz (v5.2.1, Commit e2ede08) und den geklonten Repositories. Erstellt am 03.10.2026.
Lizenzhinweis: Blockbench steht unter GPL-3.0-or-later; das Toolkit-Plugin nutzt ausschließlich die öffentliche Plugin-API.