-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
This guide installs VGui as a standalone Velocity plugin, adds the API to another plugin, and opens a first menu.
- A Velocity 4 proxy running Java 25 or newer
- A plugin project that targets Java 25
- Maven or Gradle for the dependent plugin
- VGui on the proxy at runtime
PacketEvents does not have to be installed separately. The standalone VGui release contains the PacketEvents runtime modules it needs and manages that API for its own lifecycle. Do not add a separate PacketEvents plugin solely for VGui.
Download the latest stable jar, place it in the Velocity plugins directory, and restart the proxy.
The stable asset is always named vgui.jar. The URL follows the latest GitHub release and does not contain a release number.
On startup, look for messages confirming that PacketEvents and the VGui service initialized.
Add JitPack and the VGui dependency. Use main-SNAPSHOT while developing against the newest main branch, or replace it with a vX.Y.Z release tag for a reproducible production build.
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.AgentNoobff</groupId>
<artifactId>VGUI</artifactId>
<version>main-SNAPSHOT</version>
<scope>provided</scope>
</dependency>JitPack can fetch the project directly from the repository. See Installation for Gradle and dependency details.
Make Velocity load VGui before your plugin:
@Plugin(
id = "myplugin",
dependencies = @Dependency(id = "vgui")
)
public final class MyPlugin {
}Without this dependency, your plugin may call VGui.get() before initialization and receive an IllegalStateException.
private final View selector = VGui.chest(3)
.title(Component.text("Choose a server"))
.layout(
"#########",
"#...s...#",
"####c####")
.map('#', ItemBuilder.of(ItemTypes.GRAY_STAINED_GLASS_PANE)
.name(Component.text(" "))
.asItem())
.map('s', ItemBuilder.of(ItemTypes.COMPASS)
.name(Component.text("Survival"))
.lore(Component.text("Click to connect"))
.onClick(click -> connectToSurvival(click.player())))
.map('c', ViewItem.closeButton(ItemBuilder.of(ItemTypes.BARRIER)
.name(Component.text("Close"))
.build()))
.build();The result is immutable and can be stored once. Per-player state is created when the view opens.
Call VGui.open from a command, event, or other plugin action:
VGui.open(player, selector);The proxy sends the window immediately. VGui calls the view's open handler, sends its initial contents, and registers the session for clicks and cleanup.
Grant vgui.demo and run /vgui as a player. The demo includes layouts, pagination, anvil input, live updates, navigation, and sounds. The source is also a useful integration example.
- Keep click handlers fast. They run on the player's network thread.
- Use
ViewContextfor per-player values. Do not put mutable player state in a reusableViewinstance. - Use
ViewContents.batchwhen changing several slots at once. - Leave client transaction cancellation enabled unless you implement the full inventory behavior yourself.
- Pin a release tag before shipping a production plugin.
Continue with Core Concepts, then use Examples and Recipes for larger menus.
- View Types and Builders
- Layouts and Slots
- Items and Skulls
- Click Handling
- Contents and Updates
- Context and State
- Navigation
- Pagination
- Anvil Input
- Lifecycle and Listeners
- API Reference