GUI
Überblick
GUI macht aus einem einzigen TypeWriter-Entry, Open GUI, ein vollständiges Inventarmenü. Du wählst den Container-Typ (eine Truhe, einen Amboss, ein Händlerfenster, ein beschriebenes Buch ...), schreibst einen Titel in MiniMessage und beschreibst dann den Inhalt als Baum aus Layouts, der im layoutPool des Entrys gespeichert ist. Jedes Layout platziert Items: ein Material, einen Namen, etwas Lore und was passiert, wenn ein Spieler darauf klickt.
Alles wird im Web-Panel bearbeitet: Es gibt keine Menüdateien, die du von Hand schreiben musst. Ein Menü wird wie jede andere Action geöffnet, aus einem Quest-Schritt, einem NPC-Dialog, einem Befehls-Event oder einem anderen Menü. Klicks führen Konsolenbefehle aus, lösen andere Entries aus und ändern Facts, ein Menü ist also nur eine weitere Möglichkeit, deine TypeWriter-Seiten zu steuern.
GUI ist außerdem die Grundlage der anderen BTC-Menü-Erweiterungen. Shops und Quest Codex bringen kein eigenes Fenster mit: Sie platzieren Marker-Items in einem open_gui-Layout, und die Erweiterung füllt sie mit Produkten oder Quests.
Funktionen
- Zehn Layouts —
simple,flex,paginated,scrollable,frame,composite,book,merchant,storageundleaderboard. - 24 Container-Typen — Truhengrößen von 9 bis 54 Slots, außerdem Amboss, Zaubertisch, Schmiedetisch, Steinsäge, Schleifstein, Webstuhl, Kartentisch, Händler, Buch, Trichter, Öfen und mehr.
- MiniMessage überall — Farben, Farbverläufe und PlaceholderAPI-Platzhalter in Titeln, Item-Namen und Lore.
- Klick-Aktionen pro Klicktyp — Links-, Rechts-, Shift-, Mittel- und Doppelklick, Zahlentasten, Wegwerfen und Zweithand-Tausch, jeweils mit eigenen Befehlen und Triggern.
- Slot-Berechtigungen — blende einen Slot mit
viewPermissionaus oder lass ihn mitclickPermissionsichtbar, aber wirkungslos. - Slot-Wiederholung — fülle eine Reihe oder einen Block mit
count,direction,gapundrepeatY, statt Items zu kopieren. - Views und Tabs — eine Menühülle, mehrere Bildschirme, mit Breadcrumb-Titel und Tabs, die aufleuchten.
- Persistenter Speicher — Slots, die ihre Items pro Spieler oder pro Gruppe behalten, mit Kontingenten, Platzhaltern und optionalem Fallenlassen beim Schließen.
- Bestenlisten — Ranglisten für Spieler, Welten oder Gruppen anhand eines oder mehrerer Facts, auch für Offline-Spieler, oder die Zeilen, die eine andere Erweiterung über das Feld
sourceliefert (zum Beispiel die Statistiken von Dungeon). - Erweitertes Inventar — verwandle das eigene Inventar des Spielers in vier zusätzliche Menüreihen für eine Zeichenfläche mit zehn Reihen.
Installation
- Installiere TypeWriter auf einem Paper- oder Folia-Server. PacketEvents, das TypeWriter ohnehin voraussetzt, muss vorhanden sein.
- Lade die JAR von den GUI-GitHub-Releases herunter (der Button im Übersichtsfeld oben).
- Lege sie in
plugins/Typewriter/extensions/ab und starte den Server neu. - Optional: Installiere CraftEngine, wenn deine Titel
<image>- oder<shift>-Tags nutzen, um eigene Hintergründe zu zeichnen.
Installiere GUI vor den Erweiterungen, die darauf aufbauen, wie Shops und Quest Codex.
Das öffentliche GUI-Release enthält weder einen eigenständigen Menü-Editor noch dessen Webserver: Menüs werden im TypeWriter-Web-Panel bearbeitet. Das Release liefert nur eine Startprüfung mit, die deine veröffentlichten open_gui-Entries liest und fehlerhafte Menüs in der Konsole meldet (siehe Fehlerbehebung).
Erste Schritte
So baust du ein kleines Menü mit drei Buttons:
- Öffne im Web-Panel eine Sequence-Seite und füge einen Open GUI-Entry hinzu. Nenne ihn
main_menu. - Setze
guiTypeaufCUSTOM,sizeaufSIZE_27undtitleauf<gold>Main menu. - Füge in
layoutPoolein Layout vom Typsimplehinzu, gib ihm dieidmainund trage dannmaininmainLayoutIdein. - Füge in den
itemsdes Layouts ein Item beix4,y1 hinzu. Wähle initemeinenDIAMOND, setzedisplayNameauf<aqua>Rewardsund füge einelore-Zeile<gray>Click to claimhinzu. - Füge in
interactionListeine Interaction mittypeLEFT_CLICKhinzu. Trage incommandseinen Konsolenbefehl wiegive %player% diamond 1ein oder verknüpfe einen Entry intriggers. AktivierecloseMenu, um das Menü nach dem Klick zu schließen. - Füge ein zweites
simple-Item mitcount9,directionrightund einer grauen gefärbten Glasscheibe hinzu, um eine Rahmenreihe zu zeichnen. Setze dessendisplayNameauf ein einzelnes Leerzeichen. - Verknüpfe den Open-GUI-Entry mit etwas, das ihn auslöst, zum Beispiel dem Trigger einer Dialogoption oder einem Befehls-Event, und klicke dann auf Publish.
Bring ein einzelnes simple-Layout im Spiel zum Laufen, bevor du frame-, scrollable- oder paginated-Ebenen hinzufügst. Jedes Layout wird über seine id angesprochen, ein Tippfehler in mainLayoutId ist also das Erste, was du prüfen solltest, wenn ein Menü leer öffnet.
So funktioniert es
Wird die Action ausgelöst, baut die Erweiterung den Layout-Baum für diesen Spieler auf (Criteria und Berechtigungen werden in diesem Moment ausgewertet), registriert eine Menü-Session und zeigt das Inventar an. Jeder Klick wird dem Slot an dieser Position zugeordnet und führt dann die passende Interaction aus. Die Session merkt sich vorherige Menüs, sodass gui:back zu dem Menü zurückführt, aus dem der Spieler kam.
Menüs
Container-Typen
guiType wählt das Fenster. CUSTOM ist ein einfaches truhenartiges Inventar, dessen Höhe du mit size festlegst. size gilt nur für CUSTOM und ist standardmäßig sechs Reihen groß; die anderen Typen nutzen die Vanilla-Größe ihres Fensters.
guiType | Fenster |
|---|---|
CUSTOM, CHEST, ENDER_CHEST, BARREL, SHULKER_BOX | Raster im Truhenstil. Bei CUSTOM ist size SIZE_9, SIZE_18, SIZE_27, SIZE_36, SIZE_45 oder SIZE_54. |
HOPPER, DISPENSER, DROPPER | Kleine Container mit fester Größe. |
FURNACE, BLAST_FURNACE, SMOKER, BREWING_STAND, BEACON | Maschinenfenster. |
CRAFTING_TABLE, ENCHANTING_TABLE, ANVIL, SMITHING_TABLE, GRINDSTONE, LOOM, CARTOGRAPHY_TABLE, STONECUTTER | Vanilla-Werkbänke. Ohne Layout verhalten sie sich wie der Vanilla-Bildschirm; GUI verwaltet nur das Öffnen und Schließen. |
MERCHANT, VILLAGER_TRADE | Das Dorfbewohner-Handelsfenster, gefüllt von einem merchant-Layout. |
BOOK | Ein beschriebenes Buch, gefüllt von einem book-Layout. |
Layouts
Jedes Layout ist ein benannter Eintrag des layoutPool. Das in mainLayoutId genannte ist die Wurzel; die anderen werden über Verweise erreicht (composite-Kinder, innerId eines scrollable, layoutId eines frame).
| Layout | Verwendung | Wichtige Felder |
|---|---|---|
simple | Feste Buttons und Dekoration an x/y-Positionen. | items |
flex | Automatisch in Reihen angeordnete Items. | justifyContent (START, CENTER, END, SPACE_BETWEEN), alignItems, wrap, virtualHeight |
paginated | Eine lange Liste, in Seiten aufgeteilt. | itemsPerPage, slots, items, navigationButtons (NEXT, PREVIOUS, BACK, INDICATOR) |
scrollable | Inhalt, der höher oder breiter ist als das Fenster. | innerId, virtualWidth, virtualHeight, buttons (direction, step), showDefaultButtons, defaultStep |
frame | Mehrere unabhängige Rechtecke, zum Beispiel Tabs, Inhalt und ein Footer. | frames (id, x, y, width, height, layoutId) |
composite | Gestapelte Ebenen: Hintergrund, Inhalt, Buttons. | children (Layout-IDs, spätere Kinder werden oben gezeichnet) |
book | Die Seiten eines beschriebenen Buchs. | pages (MiniMessage) |
merchant | Dorfbewohner-Handel mit eigenen Items. | trades (result, costOne, costTwo, maxUses, criteria) |
storage | Persistente Slots, gestützt auf ein GUI Storage-Artifact. | entry, groupKey, slots |
leaderboard | Rangzeilen mit Seiten, aus Facts oder aus der source einer anderen Erweiterung. | leaderboard, x, y, width, height, previousButton, nextButton |
Ein book- oder merchant-Layout funktioniert nur als Hauptlayout, und guiType wird auf das passende Fenster überschrieben. Ein scrollable-Layout erhält Standardpfeile, solange showDefaultButtons aktiv ist (Standard): einen für jede Richtung ohne Eintrag in buttons, siehe Layouts, Frames und Slots.
Eine ausführliche Erklärung jedes Layouts findest du unter Layouts, Frames und Slots.
Items und Slots
Jedes Item eines Layouts ist eine Slot-Beschreibung mit denselben Feldern:
| Feld | Aufgabe |
|---|---|
item | Das anzuzeigende Item. Bleibt es leer, zeigt der Slot das Item, das der Spieler in der Haupthand hält. |
displayName, lore | MiniMessage-Text mit PlaceholderAPI-Unterstützung. Namen sind standardmäßig aufrecht; füge <italic> hinzu, wenn du Kursivschrift möchtest. Ein leerer displayName behält den Namen des Gegenstands, statt ihn durch einen leeren zu ersetzen. |
x, y | Spalte 0 bis 8 und Reihe ab 0 oben. |
rollPerSlot | Für einen auf mehrere Slots wiederholten Gegenstand mit zufälligem item: aus (Standard) würfelt einmal, und jeder Slot zeigt dieses Ergebnis; an würfelt jeder Slot beim Öffnen des Menüs für sich. Das Ergebnis bleibt, solange das Menü geöffnet ist, außer liveItem ist an. |
liveItem | Aus (Standard): Der Gegenstand wird beim Öffnen des Menüs gezogen und für die ganze Sitzung behalten; beim Aktualisieren folgen nur Name und Beschreibung. An: Der Gegenstand wird bei jeder Aktualisierung neu ausgewertet, ein zufälliger Gegenstand wird also jedes Mal neu gezogen. Mit rollPerSlot an würfelt jeder wiederholte Slot bei jeder Aktualisierung für sich; ohne teilen sich alle wiederholten Slots eine Ziehung pro Aktualisierung. Ein leerer Name wird weiterhin ignoriert. |
count, direction, gap, repeatY | Slot-Wiederholung, siehe unten. |
criteria | Der Slot wird für Spieler, die nicht passen, nicht gezeichnet. |
viewPermission | Berechtigung, die zum Sehen des Slots nötig ist. |
clickPermission | Berechtigung, die zum Benutzen des Slots nötig ist; ohne sie wird der Slot gezeichnet, ist aber wirkungslos. |
allowPickup, isGhost | Ob das Item aus dem Menü genommen werden kann. Beide sind standardmäßig aus; Ghost-Items können angeklickt, aber nie verschoben oder kopiert werden. |
cooldownTicks | Ticks, bevor derselbe Slot erneut angeklickt werden kann. |
interactionList, triggers, modifiers | Was ein Klick bewirkt. |
input | Öffnet beim Klick einen Texteingabe-Dialog. |
storageId | Macht den Slot zu einem persistenten Speicher-Slot aus storagePool. |
buttonType, buttonPrefix | Markiert den Slot als Button, der von einer anderen Erweiterung bereitgestellt wird. |
animation | Bewegt den Slot beim Öffnen des Menüs über eine Dauer in Millisekunden an eine Zielposition. |
Slot-Wiederholung. count wiederholt ein Item entlang direction (right, left, down, up). gap ist eine Schrittweite, kein Abstand: 1 bedeutet benachbart, 2 lässt einen leeren Slot zwischen den Kopien, und 0 verhält sich wie 1. repeatY wiederholt die ganze Zeile auf der senkrechten Achse. Ohne direction werden count, gap und repeatY ignoriert und es wird ein einzelner Slot platziert. Diese Felder zählen Slots, nie die Stapelgröße des Items.
Überlappungen. Teilen sich zwei Slots eine Zelle, gewinnt der, der etwas bewirkt (eine Klick-Aktion, ein Tag, ein Speicher-Slot), gegenüber einem rein dekorativen, unabhängig von der Reihenfolge. Bei zwei gleichartigen gewinnt der zuletzt deklarierte. Eine Warnung mit der Zelle wird einmal protokolliert.
Klick-Aktionen
interactionList ordnet einem Klicktyp Befehle und Trigger zu. Die verfügbaren Typen sind LEFT_CLICK, RIGHT_CLICK, SHIFT_LEFT_CLICK, SHIFT_RIGHT_CLICK, MIDDLE_CLICK, DOUBLE_CLICK, NUMBER_KEY_1 bis NUMBER_KEY_9, DROP, DROP_ALL und SWAP_OFFHAND.
commandswerden von der Konsole ausgeführt.%player%wird durch den Spielernamen ersetzt, und PlaceholderAPI-Platzhalter werden zuerst aufgelöst.triggerslösen TypeWriter-Entries für den Spieler aus. Die eigenentriggersundmodifiersdes Slots werden bei jedem Links- oder Rechtsklick ausgelöst oder immer dann, wenn eine bestimmte Interaction passt.closeMenuschließt das Fenster nach der Action.executeReturngeht zum vorherigen Menü zurück.
Befehle, die mit gui: beginnen, werden von GUI selbst verarbeitet:
| Befehl | Wirkung |
|---|---|
gui:close | Schließt das Menü. |
gui:back | Öffnet das vorherige Menü der Session erneut. |
gui:open <entry_id> oder gui:action <entry_id> | Löst einen anderen Entry aus, meist ein weiteres Open GUI. |
gui:view <view_id> | Wechselt zu einer anderen View, ohne das Inventar zu schließen. |
gui:page <delta> [layout_id] | Bewegt ein paginiertes oder Leaderboard-Layout um so viele Seiten. |
gui:scroll <dx> <dy> [layout_id] | Scrollt ein scrollable-Layout. |
gui:refresh | Zeichnet das Menü sofort neu. |
gui:sound <sound_key> | Spielt dem Spieler einen Sound vor. |
Öffnen, Zurück und Schließen
Ein Open GUI, das aus einem anderen Menü geöffnet wird, wird auf den Session-Verlauf gelegt, sodass gui:back oder executeReturn dorthin zurückführt. Das Schließen mit Escape beendet die Session. Das Öffnen eines Buch-Layouts beendet zuerst die aktuelle Session.
Setze audio, um beim Öffnen, Schließen, Scrollen und Klicken Sounds abzuspielen. Setze autoRefreshTicks, um das Menü bei geöffnetem Zustand alle N Ticks neu zu zeichnen; dadurch ticken Platzhalter in Namen und Lore wie ein Zähler oder Timer.
Views, Tabs und Vererbung
views machen aus einem open_gui mehrere Bildschirme, die dieselbe Hülle teilen. Ein frame, dessen layoutId @view ist, wird mit dem Layout der aktiven View gefüllt: zuerst über die explizite frames-Zuordnung der View, dann über das Layout mit dem Namen <view id>_<frame id>, dann über dieselben Suchen entlang der parentId der View. Markiere ein Tab-Item mit buttonPrefix view: und buttonType gleich der View-ID, dann wechselt es beim Klick die View und leuchtet auf, solange sie aktiv ist. Der View-Titel akzeptiert {breadcrumb}, {view} und {root}.
baseMenuId verweist auf ein anderes Open GUI und führt dessen layoutPool, views und storagePool unter deinen zusammen: Ein Layout mit derselben id ersetzt das geerbte. Details unter Views, Tabs und Vererbung.
Speicher-Slots
Ein GUI Storage-Artifact hält die Items, pro Spieler oder pro Gruppe. Deklariere wiederverwendbare Konfigurationen im storagePool des Entrys und gib dann einem Item eine storageId oder verwende ein storage-Layout. Item-Namen und Lore eines Speicher-Slots akzeptieren {stored_name}, {stored_amount} und {stored_max}. {score_raw} und {value_<key>} gibt es außerdem für die Zeilen einer Bestenliste mit source.
Standard-Klickbelegungen, die du in den GUI Global Settings ändern kannst:
| Aktion | Standard-Klick |
|---|---|
| Ein Item vom Cursor ablegen | Linksklick |
| Den ganzen Cursor-Stapel ablegen | Shift + Linksklick |
| Ein Item entnehmen | Rechtsklick |
| Alles entnehmen | Linksklick |
| Einen Stapel entnehmen | Shift + Rechtsklick |
| Aus dem Inventar füllen | Zweithand tauschen (F) |
| Alles auf den Boden fallen lassen | Wegwerfen (Q) |
dropOnClose lässt das, was noch gespeichert ist, den Spieler vor die Füße fallen, wenn das Menü wirklich geschlossen wird, mit Escape oder beim Trennen der Verbindung, aber nicht, wenn der Spieler in ein anderes Menü wechselt.
Erweitertes Inventar
extendToPlayerInventory zeigt die 36 eigenen Slots des Spielers als vier zusätzliche Reihen an, für eine Zeichenfläche mit zehn Reihen (y 0 bis 9). Das geschieht nur clientseitig: Das echte Inventar wird nie verändert und beim Schließen des Menüs wiederhergestellt, und aus den unteren Reihen können keine Items aufgenommen werden. Es erfordert guiType CUSTOM mit size SIZE_54. Ein Wurzel-Layout, dessen id auf _extended endet, aktiviert es von selbst.
Konfiguration
GUI hat keine Konfigurationsdatei. Zwei optionale Manifest-Entries passen es an:
- GUI Extension Configuration aktiviert das
debug-Logging und die OptionhideVanillaItemStats, standardmäßig an, die Angriffsschaden-, Haltbarkeits- und Verzauberungszeilen auf Menü-Buttons ausblendet. - GUI Global Settings legt die Klickbelegungen des Speichers und die Connector-Items des Skilltrees fest.
Platzhalter
| Platzhalter | Liefert |
|---|---|
%typewriter_gui_storage_amount_<entry_id>_<slot_index>% | Anzahl der für den Spieler in einem GUI Storage-Entry gespeicherten Items, 0 wenn leer. |
%typewriter_gui_storage_has_<entry_id>_<slot_index>% | true, wenn der Slot ein Item enthält, sonst false. |
<slot_index> ist y * 9 + x des Speicher-Slots. Diese Platzhalter lesen immer den eigenen Speicher des Spielers, nie einen gemeinsamen Gruppenspeicher.
In Menüs werden die folgenden Token von der Erweiterung ersetzt: {stored_name}, {stored_amount}, {stored_max} (Speicher-Slots), {page}, {next_page}, {prev_page}, {total_pages} und {page_indicator} (der INDICATOR-Button eines paginierten Layouts) sowie {rank}, {name}, {score}, {group}, {world} und {score_<fact_id>} (Leaderboard-Zeilen).
Entries
6 Einträge, aus dem Quellcode der Erweiterung generiert.
Aktionen1
- Open GUIOpen a GUI for the player
Artefakte2
- GUI Leaderboard PopulationOffline population data for GUI leaderboards
- GUI StoragePersistent storage artifact for GUI storage slots
Manifeste3
- GUI ConfigGUI Extension Configuration
- GUI LeaderboardGUI leaderboard backed by Typewriter facts
- GUI SettingsGUI Global Settings
Fehlerbehebung
Das Menü öffnet sich leer. mainLayoutId ist leer oder passt zu keiner Layout-id im layoutPool (IDs unterscheiden Groß- und Kleinschreibung). Bei Verwendung von baseMenuId greift eine leere mainLayoutId auf die des Elternteils zurück. Die Startprüfung meldet ein nicht aufgelöstes Hauptlayout in der Konsole.
Ein Slot fehlt und die Konsole meldet „falls outside the grid“. Das Item landete bei einem negativen x oder y oder hinter Spalte 8. Meist liegt das an einem zu großen count, der Slots zählt. Das Log nennt das Layout und die abgelehnten Koordinaten.
Die Konsole meldet „Slot overlap ... gap“. Zwei Slots teilen sich eine Zelle. gap ist eine Schrittweite: 1 platziert benachbarte Slots und 2 lässt jeweils einen leeren Slot dazwischen; wer gap: 1 als „eine Lücke“ liest, erhält Kopien, die auf den Nachbarn der jeweils anderen liegen. Ändere gap oder verschiebe einen Slot.
Ein Slot ist für Admins sichtbar, aber nicht für Spieler. viewPermission nennt eine Berechtigung, die außer Operatoren niemand hat. Leere Werte werden ignoriert, aber ein Tippfehler ist ein echter, nur für Operatoren geltender Node. Dieselbe Regel gilt für die viewPermission einer View.
Ein Button wird angezeigt, tut aber nichts. Prüfe clickPermission, dann cooldownTicks, dann criteria. Hat der Slot einen buttonType, muss sein buttonPrefix zur bereitstellenden Erweiterung passen; ein nicht beanspruchtes Tag behält deine eigene interactionList, aber sonst nichts. Befehle werden von der Konsole ausgeführt, ein Befehl, der einen Spieler als Absender braucht, schlägt daher stillschweigend fehl.
Der scrollbare Inhalt bewegt sich nicht. Prüfe, ob der Inhalt größer als das Fenster ist (virtualWidth und virtualHeight): Ein Pfeil erscheint nur, solange es in seiner Richtung etwas zu scrollen gibt. Ist showDefaultButtons aus und gibt es keine buttons, gibt es überhaupt keinen Pfeil. Ein Standardpfeil weicht außerdem aus, wenn seine Zelle bereits ein Inhalts-Item, einen Button oder eine Dekoration enthält: Es wird nichts protokolliert, verschiebe ihn also mit scrollArrows in GUI Settings oder füge eigene buttons mit einer direction und einem step außerhalb des gescrollten Bereichs hinzu.
Das Leaderboard listet nur Online-Spieler auf. Verknüpfe ein GUI Leaderboard Population-Artifact im Feld population des Leaderboards, um die zuletzt bekannten Werte von Offline-Spielern zu behalten.
Das erweiterte Menü zeigt keine zehn Reihen. extendToPlayerInventory erfordert guiType CUSTOM und size SIZE_54.
Verwandte Erweiterungen
- Shops — Shop-Menüs, aufgebaut auf GUI-Layouts und dem Marker
shop_button:. - Quest Codex — das Quest-Log-Menü, aufgebaut auf demselben
open_gui-Chassis.