Files
GeyserWebsite/_site/geyser/forms/index.html
T
2023-11-07 19:40:55 -06:00

571 lines
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8">
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GeyserMC Wiki: Forms and Cumulus</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/darcula.css">
<meta name="author" content="GeyserMC">
<meta name="description" content="This is the wiki for all of GeyserMC's projects.">
<meta name="theme-color" content="#2b3035">
<meta property="og:type" content="website">
<meta property="og:url" content="http://localhost:4000">
<meta property="og:title" content="GeyserMC Wiki: Forms and Cumulus">
<meta property="og:description" content="This is the wiki for all of GeyserMC's projects.">
<meta property="og:image" content="/android-chrome-192x192.png">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="192x192" href="/android-chrome-192x192.png">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#248f00">
</head>
<body>
<header>
<nav class="navbar navbar-expand-lg bg-body-tertiary fixed-top">
<div class="container-fluid">
<a class="navbar-brand" href="/"><img src="/android-chrome-512x512.png" alt="geyser logo" height="32"> GeyserMC Wiki</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarLinks" aria-controls="navbarLinks" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarLinks">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="https://geysermc.org/"><i class="bi bi-house pe-1"></i> Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://geysermc.org/download"><i class="bi bi-download pe-1"></i> Download</a>
</li>
</ul>
<form class="d-flex" role="search" action="/search/">
<div class="input-group">
<button class="btn btn-outline-secondary" type="submit" id="button-search"><i class="bi bi-search"></i></button>
<input type="text" name="q" class="form-control" placeholder="Search the site..." aria-label="Search the site..." aria-describedby="button-search">
</div>
</form>
</div>
</div>
</nav>
</header>
<div id="page-content" class="container-fluid">
<div class="row">
<div class="col-12 col-md-3 col-xl-2">
<div class="sticky-top">
<div class="sidebar py-2 text-break">
<nav class="navbar navbar-expand-md">
<div class="container-fluid">
<div class="d-block d-md-none">Wiki Navigation</div>
<button class="navbar-toggler mb-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarNav" aria-controls="sidebarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse flex-column align-items-start" id="sidebarNav">
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle fw-bold show" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="false" aria-expanded="false">Geyser Documentation</a>
<ul class="pe-3 pt-0 dropdown-menu position-relative border-0 list-disc show">
<li class="ms-4">
<a href="/geyser/setup/">Setting up Geyser</a>
<ul>
<li>
<a href="/geyser/supported-hosting-providers/">Supported Hosting Providers</a>
</li>
<li>
<a href="/geyser/using-geyser-with-consoles/">Using Geyser with Consoles</a>
</li>
<li>
<a href="/geyser/playit-gg/">Using playit.gg with Geyser</a>
</li>
<li>
<a href="/geyser/creating-a-startup-script/">Creating a Startup Script</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/common-issues/">Common Issues</a>
<ul>
<li>
<a href="/geyser/fixing-unable-to-connect-to-world/">Fixing 'Unable to Connect to World'</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/understanding-the-config/">Configuring Geyser</a>
<ul>
<li>
<a href="/geyser/commands/">Commands</a>
</li>
<li>
<a href="/geyser/geyser-command-line-arguments-and-system-properties/">Geyser Command Line Arguments and System Properties</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/faq/">FAQ</a>
<ul>
<li>
<a href="/geyser/anticheat-compatibility/">Anticheat Compatibility</a>
</li>
<li>
<a href="/geyser/current-limitations/">Current Limitations</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/custom-items/">Custom items with Geyser</a>
<ul>
<li>
<a href="/geyser/custom-items/#json-mappings">JSON mappings</a>
</li>
<li>
<a href="/geyser/custom-items/#geyser-extensions">Geyser extensions</a>
</li>
<li>
<a href="/geyser/custom-items/#resource-pack">Resource pack</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/custom-blocks/">Custom blocks with Geyser</a>
<ul>
<li>
<a href="/geyser/custom-blocks/#enabling-custom-blocks">Enabling custom blocks</a>
</li>
<li>
<a href="/geyser/custom-blocks/#json-mappings">JSON mappings</a>
</li>
<li>
<a href="/geyser/custom-blocks/#geyser-extensions">Geyser extensions</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/custom-skulls/">Custom skulls with Geyser</a>
<ul>
<li>
<a href="/geyser/custom-skulls/#enabling-custom-skulls">Enabling custom skulls</a>
</li>
<li>
<a href="/geyser/custom-skulls/#custom-skullsyml">custom-skulls.yml</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/api/">Geyser API</a>
<ul>
<li>
<a href="/geyser/getting-started-with-the-api/">Getting Started</a>
</li>
<li>
<a href="/geyser/api/#short-overview-of-the-geyser-api">Overview</a>
</li>
<li>
<a href="/geyser/events/">Events</a>
</li>
<li>
<a href="/geyser/forms/">Forms and Cumulus</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/extensions/">Geyser Extensions</a>
<ul>
<li>
<a href="/geyser/extensions/#creating-the-main-class">Main class</a>
</li>
<li>
<a href="/geyser/extensions/#creating-commands-with-geyser-extensions">Creating Commands</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/global-api/">Global API</a>
</li>
</ul>
</div>
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle fw-bold" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="false" aria-expanded="false">Floodgate Documentation</a>
<ul class="pe-3 pt-0 dropdown-menu position-relative border-0 list-disc">
<li class="ms-4">
<a href="/floodgate/setup/">Setup</a>
</li>
<li class="ms-4">
<a href="/floodgate/issues/">Issues</a>
</li>
<li class="ms-4">
<a href="/floodgate/faq/">FAQ</a>
</li>
<li class="ms-4">
<a href="/floodgate/features/">Features</a>
<ul>
<li>
<a href="/floodgate/features/#whitelist-command">Whitelist command</a>
</li>
<li>
<a href="/floodgate/commands/">Commands</a>
</li>
<li>
<a href="/floodgate/features/#what-is-skin-uploading">Skin Uploading</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/floodgate/api/">Floodgate API</a>
<ul>
<li>
<a href="/floodgate/player/">FloodgatePlayer</a>
</li>
<li>
<a href="/geyser/forms/">Forms and Cumulus</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/floodgate/linking/">Linking</a>
<ul>
<li>
<a href="/floodgate/linking/#what-is-global-linking">Global Linking</a>
</li>
<li>
<a href="/floodgate/linking/#local-linking">Local Linking</a>
</li>
</ul>
</li>
</ul>
</div>
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle fw-bold" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="false" aria-expanded="false">Other</a>
<ul class="pe-3 pt-0 dropdown-menu position-relative border-0 list-disc">
<li class="ms-4">
<a href="/other/geyseroptionalpack/">GeyserOptionalPack</a>
</li>
<li class="ms-4">
<a href="/other/hurricane/">Hurricane</a>
</li>
<li class="ms-4">
<a href="/other/geyserconnect/">GeyserConnect</a>
</li>
<li class="ms-4">
<a href="/other/community-geyser-projects/">Community Geyser Projects</a>
</li>
<li class="ms-4">
<a href="/other/test-server/">Test Server</a>
</li>
<li class="ms-4">
<a href="/other/developer-guide/">Developer Guide</a>
</li>
<li class="ms-4">
<a href="/other/discord-bot-usage/">Geyser Discord Bot Usage</a>
</li>
</ul>
</div>
</div>
</div>
</nav>
</div>
</div>
</div>
<main class="col-12 col-md-9 col-xl-8" role="main">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="http://localhost:4000/geyser/">Geyser</a></li>
<li class="breadcrumb-item active" aria-current="page">Forms and Cumulus</li>
</ol>
</nav>
<h1 id="what-is-cumulus">What is Cumulus?</h1>
<p>Bedrock Edition has a cool exclusive feature called Forms.<br />
Cumulus is the Forms API that we use in Geyser and Floodgate.<br />
The source code is available <a href="https://github.com/GeyserMC/Cumulus">here</a>. You can access the Cumulus API through the <a href="/floodgate/api/">Floodgate API</a>, or the <a href="/geyser/api">Geyser API</a>.</p>
<p>Bedrock knows three types of Forms:</p>
<ul>
<li>ModalForm</li>
<li>SimpleForm</li>
<li>CustomForm</li>
</ul>
<p>We’ll discuss them one by one starting with the easiest and ending with the least easy form type.<br />
After that, you get an overview of every single component.<br />
Then we’ll talk about sending the form, receiving a response and doing advanced stuff.<br /></p>
<h2 id="modalform">ModalForm</h2>
<p>While this is the easiest form type it’s also the least customisable.<br />
You have a title, description (content) and two buttons.</p>
<p><img src="https://i.imgur.com/kMpMgOh.png" alt="Example of a ModalForm" /></p>
<p>Code used in the image:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ModalForm</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">title</span><span class="o">(</span><span class="s">"Title"</span><span class="o">)</span>
<span class="o">.</span><span class="na">content</span><span class="o">(</span><span class="s">"Content"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button1</span><span class="o">(</span><span class="s">"Button 1"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button2</span><span class="o">(</span><span class="s">"Button 2"</span><span class="o">)</span>
</code></pre></div></div>
<h2 id="simpleform">SimpleForm</h2>
<p>While this one is less easy than ModalForm is, it also has more customizability.<br />
It’s still limited to a title, content and buttons, but these buttons can also have images and do not have a minimum and maximum of two.</p>
<p><img src="https://i.imgur.com/3rj2OQ2.png" alt="Example of a SimpleForm" /></p>
<p>Code used in the image:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">SimpleForm</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">title</span><span class="o">(</span><span class="s">"Title"</span><span class="o">)</span>
<span class="o">.</span><span class="na">content</span><span class="o">(</span><span class="s">"Content"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button</span><span class="o">(</span><span class="s">"Button without an image"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button</span><span class="o">(</span><span class="s">"Button with URL image"</span><span class="o">,</span> <span class="nc">FormImage</span><span class="o">.</span><span class="na">Type</span><span class="o">.</span><span class="na">URL</span><span class="o">,</span> <span class="s">"https://github.com/GeyserMC.png?size=200"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button</span><span class="o">(</span><span class="s">"Button with path image"</span><span class="o">,</span> <span class="nc">FormImage</span><span class="o">.</span><span class="na">Type</span><span class="o">.</span><span class="na">PATH</span><span class="o">,</span> <span class="s">"textures/i/glyph_world_template.png"</span><span class="o">)</span>
</code></pre></div></div>
<h2 id="customform">CustomForm</h2>
<p>While the CustomForm is the last one on our list (and thus the least easy one), it also has the greatest customizability.<br />
This form exists of a title, content and a list of different components e.g. label, slider and input.<br />
See <a href="https://github.com/GeyserMC/Cumulus/tree/master/src/main/java/org/geysermc/cumulus/component">Components</a> for more information about every component you can use and in which form type.</p>
<p><img src="https://i.imgur.com/zHgxELm.png" alt="Example of a CustomForm" /></p>
<p>Code used in the image:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">CustomForm</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">title</span><span class="o">(</span><span class="s">"Title"</span><span class="o">)</span>
<span class="o">.</span><span class="na">dropdown</span><span class="o">(</span><span class="s">"Text"</span><span class="o">,</span> <span class="s">"Option 1"</span><span class="o">,</span> <span class="s">"Option 2"</span><span class="o">)</span>
<span class="o">.</span><span class="na">input</span><span class="o">(</span><span class="s">"Input"</span><span class="o">,</span> <span class="s">"placeholder"</span><span class="o">)</span>
<span class="o">.</span><span class="na">toggle</span><span class="o">(</span><span class="s">"Toggle"</span><span class="o">)</span>
<span class="o">.</span><span class="na">slider</span><span class="o">(</span><span class="s">"Text"</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">10</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">5</span><span class="o">)</span>
</code></pre></div></div>
<h2 id="sending-a-form">Sending a form</h2>
<p>After you decided which form type you want to use and finished filling in the actual content, it’s time to send the Form to the Bedrock player.<br />
You can do that by calling the API and send a form to the player’s UUID and the form:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">FloodgateApi</span><span class="o">.</span><span class="na">getInstance</span><span class="o">().</span><span class="na">sendForm</span><span class="o">(</span><span class="n">uuid</span><span class="o">,</span> <span class="n">form</span><span class="o">);</span> <span class="c1">// or #sendForm(uuid, formBuilder)</span>
</code></pre></div></div>
<p>Or you can do it by using the Player’s FloodgatePlayer instance:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">FloodgatePlayer</span> <span class="n">player</span> <span class="o">=</span> <span class="nc">FloodgateApi</span><span class="o">.</span><span class="na">getInstance</span><span class="o">().</span><span class="na">getPlayer</span><span class="o">(</span><span class="n">uuid</span><span class="o">);</span>
<span class="n">player</span><span class="o">.</span><span class="na">sendForm</span><span class="o">(</span><span class="n">form</span><span class="o">);</span> <span class="c1">// or #sendForm(formBuilder)</span>
</code></pre></div></div>
<p>So you can make and send forms in a pretty compact way by doing something like this:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">FloodgatePlayer</span> <span class="n">player</span> <span class="o">=</span> <span class="nc">FloodgateApi</span><span class="o">.</span><span class="na">getInstance</span><span class="o">().</span><span class="na">getPlayer</span><span class="o">(</span><span class="n">uuid</span><span class="o">);</span>
<span class="o">...</span>
<span class="n">player</span><span class="o">.</span><span class="na">sendForm</span><span class="o">(</span>
<span class="nc">CustomForm</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">title</span><span class="o">(</span><span class="s">"My cool title"</span><span class="o">)</span>
<span class="o">.</span><span class="na">label</span><span class="o">(</span><span class="s">"10/10 content"</span><span class="o">)</span>
<span class="o">);</span>
</code></pre></div></div>
<h2 id="receiving-a-response-from-the-client">Receiving a response from the client</h2>
<p>It’s nice and all that we can send forms to a client, but we also want to be able to get a response from a client and being able to handle them.<br />
We can do that using one (or multiple) result handers. The most used result handlers are: <code class="language-plaintext highlighter-rouge">validResultHandler(BiConsumer&lt;Form, ValidFormResponseResult&gt; | Consumer&lt;ValidFormResponseResult&gt;)</code>, <code class="language-plaintext highlighter-rouge">invalidResultHandler</code>, <code class="language-plaintext highlighter-rouge">closedResultHandler</code> and <code class="language-plaintext highlighter-rouge">closedOrInvalidResultHandler</code>.<br />
Here follows an example that uses result handlers:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">CustomForm</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">title</span><span class="o">(</span><span class="s">"geyser.auth.login.form.details.title"</span><span class="o">)</span>
<span class="o">.</span><span class="na">label</span><span class="o">(</span><span class="s">"geyser.auth.login.form.details.desc"</span><span class="o">)</span>
<span class="o">.</span><span class="na">input</span><span class="o">(</span><span class="s">"geyser.auth.login.form.details.email"</span><span class="o">,</span> <span class="s">"account@geysermc.org"</span><span class="o">,</span> <span class="s">""</span><span class="o">)</span>
<span class="o">.</span><span class="na">input</span><span class="o">(</span><span class="s">"geyser.auth.login.form.details.pass"</span><span class="o">,</span> <span class="s">"123456"</span><span class="o">,</span> <span class="s">""</span><span class="o">)</span>
<span class="o">.</span><span class="na">closedOrInvalidResultHandler</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">buildAndShowLoginDetailsWindow</span><span class="o">(</span><span class="n">session</span><span class="o">))</span>
<span class="o">.</span><span class="na">validResultHandler</span><span class="o">(</span><span class="n">response</span> <span class="o">-&gt;</span> <span class="n">session</span><span class="o">.</span><span class="na">authenticate</span><span class="o">(</span><span class="n">response</span><span class="o">.</span><span class="na">next</span><span class="o">(),</span> <span class="n">response</span><span class="o">.</span><span class="na">next</span><span class="o">())));</span>
</code></pre></div></div>
<h2 id="advanced-stuff">Advanced stuff</h2>
<p>The FormBuilder also has support for translating the data used in the builder.<br />
To add a translator, you can use the <code class="language-plaintext highlighter-rouge">translator(BiFunction&lt;String, String, String&gt;)</code> or the <code class="language-plaintext highlighter-rouge">translator(BiFunction&lt;String, String, String&gt;, String)</code> method:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ModalForm</span> <span class="n">form</span> <span class="o">=</span> <span class="nc">ModalForm</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">translator</span><span class="o">(</span><span class="k">this</span><span class="o">::</span><span class="n">translate</span><span class="o">,</span> <span class="n">userLanguage</span><span class="o">)</span>
<span class="o">.</span><span class="na">title</span><span class="o">(</span><span class="s">"Title"</span><span class="o">)</span>
<span class="o">.</span><span class="na">content</span><span class="o">(</span><span class="s">"Content"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button1</span><span class="o">(</span><span class="s">"translate.button1"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button2</span><span class="o">(</span><span class="s">"translate.button2"</span><span class="o">)</span>
<span class="o">.</span><span class="na">build</span><span class="o">();</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">translate</span><span class="o">(</span><span class="nc">String</span> <span class="n">key</span><span class="o">,</span> <span class="nc">String</span> <span class="n">locale</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// this method will be called for every string, in this case, 4 times:</span>
<span class="c1">// Title, Content, translate.button1, translate.button2</span>
<span class="c1">// your own translate logic here</span>
<span class="c1">// return the value that replaces the key</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Or you can have the translate method directly in the FormBuilder instead of a separate method:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ModalForm</span> <span class="n">form</span> <span class="o">=</span> <span class="nc">ModalForm</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
<span class="o">.</span><span class="na">translator</span><span class="o">((</span><span class="n">key</span><span class="o">,</span> <span class="n">unused</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span>
<span class="c1">// this method will be called for every string, in this case, 4 times:</span>
<span class="c1">// Title, Content, translate.button1, translate.button2</span>
<span class="c1">// since this isn't a separate method, you don't need the locale argument, so it's unused.</span>
<span class="c1">// your own translate logic here</span>
<span class="c1">// return the value that replaces the key</span>
<span class="o">})</span>
<span class="o">.</span><span class="na">title</span><span class="o">(</span><span class="s">"Title"</span><span class="o">)</span>
<span class="o">.</span><span class="na">content</span><span class="o">(</span><span class="s">"Content"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button1</span><span class="o">(</span><span class="s">"translate.button1"</span><span class="o">)</span>
<span class="o">.</span><span class="na">button2</span><span class="o">(</span><span class="s">"translate.button2"</span><span class="o">)</span>
<span class="o">.</span><span class="na">build</span><span class="o">();</span>
</code></pre></div></div>
</main>
<div class="col-2 d-none d-xl-block">
<div class="sticky-top">
<div class="sidebar py-2">
<a class="d-block text-decoration-none" href="https://github.com/GeyserMC/GeyserWiki/edit/master/_docs/geyser/forms.md" target="_blank"><i class="bi bi-pencil"></i> Edit this page</a>
<a class="d-block text-decoration-none" href="https://github.com/GeyserMC/GeyserWiki/issues/new?labels=question&title=Question:&body=Question on: _docs/geyser/forms.md" target="_blank"><i class="bi bi-github"></i> Create Wiki issue/bug report</a>
<a class="d-block text-decoration-none" href="/issues/new" target="_blank"><i class="bi bi-list-check"></i> Create Geyser issue/bug report</a>
<div id="page-nav" class="py-3 "></div>
</div>
</div>
</div>
</div>
</div>
<!-- <footer class="p-4 text-center bg-body-tertiary">
&copy; 2023 GeyserMC
</footer> -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
<script src="/js/page-nav.js"></script>
</body>
</html>