# Table of Contents - [Paper Documentation | PaperMC Docs](#paper-documentation-papermc-docs) - [Welcome | PaperMC Docs](#welcome-papermc-docs) - [Adventure | PaperMC Docs](#adventure-papermc-docs) - [Audiences | PaperMC Docs](#audiences-papermc-docs) - [Books | PaperMC Docs](#books-papermc-docs) - [Community libraries | PaperMC Docs](#community-libraries-papermc-docs) - [Folia Documentation | PaperMC Docs](#folia-documentation-papermc-docs) - [Boss bars | PaperMC Docs](#boss-bars-papermc-docs) - [FAQ | PaperMC Docs](#faq-papermc-docs) - [Frequently asked questions | PaperMC Docs](#frequently-asked-questions-papermc-docs) - [Administration | PaperMC Docs](#administration-papermc-docs) - [Reference | PaperMC Docs](#reference-papermc-docs) - [Region logic | PaperMC Docs](#region-logic-papermc-docs) - [Overview | PaperMC Docs](#overview-papermc-docs) - [Contact us | PaperMC Docs](#contact-us-papermc-docs) - [Art assets | PaperMC Docs](#art-assets-papermc-docs) - [Diff viewer | PaperMC Docs](#diff-viewer-papermc-docs) - [MiniMessage web editor | PaperMC Docs](#minimessage-web-editor-papermc-docs) - [Item command converter | PaperMC Docs](#item-command-converter-papermc-docs) - [Getting started | PaperMC Docs](#getting-started-papermc-docs) - [Tools | PaperMC Docs](#tools-papermc-docs) - [Start script generator | PaperMC Docs](#start-script-generator-papermc-docs) - [Miscellaneous | PaperMC Docs](#miscellaneous-papermc-docs) - [Installing or updating Java | PaperMC Docs](#installing-or-updating-java-papermc-docs) - [Localization | PaperMC Docs](#localization-papermc-docs) - [Migrating from Adventure 4.x to 5.x | PaperMC Docs](#migrating-from-adventure-4-x-to-5-x-papermc-docs) - [Hangar auto-publishing | PaperMC Docs](#hangar-auto-publishing-papermc-docs) - [Migration | PaperMC Docs](#migration-papermc-docs) - [Migrating from text 3.x | PaperMC Docs](#migrating-from-text-3-x-papermc-docs) - [Downloads Service | PaperMC Docs](#downloads-service-papermc-docs) - [MiniMessage | PaperMC Docs](#minimessage-papermc-docs) - [Configuration | PaperMC Docs](#configuration-papermc-docs) - [Waterfall Documentation | PaperMC Docs](#waterfall-documentation-papermc-docs) - [Migrating from the BungeeCord Chat API | PaperMC Docs](#migrating-from-the-bungeecord-chat-api-papermc-docs) - [Getting started | PaperMC Docs](#getting-started-papermc-docs) - [Implementing platforms | PaperMC Docs](#implementing-platforms-papermc-docs) - [Native support | PaperMC Docs](#native-support-papermc-docs) - [Dynamic replacements | PaperMC Docs](#dynamic-replacements-papermc-docs) - [MiniMessage translator | PaperMC Docs](#minimessage-translator-papermc-docs) - [ViaVersion | PaperMC Docs](#viaversion-papermc-docs) - [Format | PaperMC Docs](#format-papermc-docs) - [MiniMessage API | PaperMC Docs](#minimessage-api-papermc-docs) - [Bukkit | PaperMC Docs](#bukkit-papermc-docs) - [Version history | PaperMC Docs](#version-history-papermc-docs) - [Resource packs | PaperMC Docs](#resource-packs-papermc-docs) - [BungeeCord | PaperMC Docs](#bungeecord-papermc-docs) - [adventure-platform-mod | PaperMC Docs](#adventure-platform-mod-papermc-docs) - [SpongeAPI | PaperMC Docs](#spongeapi-papermc-docs) - [ANSI | PaperMC Docs](#ansi-papermc-docs) - [Modded (Fabric and NeoForge shared API) | PaperMC Docs](#modded-fabric-and-neoforge-shared-api-papermc-docs) - [Fabric | PaperMC Docs](#fabric-papermc-docs) - [Player list/Tab list | PaperMC Docs](#player-list-tab-list-papermc-docs) - [JSON | PaperMC Docs](#json-papermc-docs) - [Gson | PaperMC Docs](#gson-papermc-docs) - [Sound | PaperMC Docs](#sound-papermc-docs) - [Titles | PaperMC Docs](#titles-papermc-docs) - [adventure-platform | PaperMC Docs](#adventure-platform-papermc-docs) - [Plain | PaperMC Docs](#plain-papermc-docs) - [Platforms | PaperMC Docs](#platforms-papermc-docs) - [NeoForge | PaperMC Docs](#neoforge-papermc-docs) - [Legacy | PaperMC Docs](#legacy-papermc-docs) - [adventure | PaperMC Docs](#adventure-papermc-docs) - [Text (Chat Components) | PaperMC Docs](#text-chat-components-papermc-docs) - [Text serializers | PaperMC Docs](#text-serializers-papermc-docs) - [Libraries used | PaperMC Docs](#libraries-used-papermc-docs) - [Comparing with other proxies | PaperMC Docs](#comparing-with-other-proxies-papermc-docs) - [How-to guides | PaperMC Docs](#how-to-guides-papermc-docs) - [Built-in commands | PaperMC Docs](#built-in-commands-papermc-docs) - [Getting started | PaperMC Docs](#getting-started-papermc-docs) - [Migration guide | PaperMC Docs](#migration-guide-papermc-docs) - [Velocity Documentation | PaperMC Docs](#velocity-documentation-papermc-docs) - [Configuring Velocity | PaperMC Docs](#configuring-velocity-papermc-docs) - [How-to guides | PaperMC Docs](#how-to-guides-papermc-docs) - [Getting started | PaperMC Docs](#getting-started-papermc-docs) - [Porting your plugin from Velocity 1.x.x | PaperMC Docs](#porting-your-plugin-from-velocity-1-x-x-papermc-docs) - [Common pitfalls | PaperMC Docs](#common-pitfalls-papermc-docs) - [Dependency management | PaperMC Docs](#dependency-management-papermc-docs) - [Securing your servers | PaperMC Docs](#securing-your-servers-papermc-docs) - [Server compatibility | PaperMC Docs](#server-compatibility-papermc-docs) - [Reference | PaperMC Docs](#reference-papermc-docs) - [API | PaperMC Docs](#api-papermc-docs) - [Velocity plugin basics | PaperMC Docs](#velocity-plugin-basics-papermc-docs) - [What does Velocity do for me? | PaperMC Docs](#what-does-velocity-do-for-me-papermc-docs) - [Using the scheduler | PaperMC Docs](#using-the-scheduler-papermc-docs) - [Frequently asked questions | PaperMC Docs](#frequently-asked-questions-papermc-docs) - [Configuring player information forwarding | PaperMC Docs](#configuring-player-information-forwarding-papermc-docs) - [Plugin messaging | PaperMC Docs](#plugin-messaging-papermc-docs) - [Working with events | PaperMC Docs](#working-with-events-papermc-docs) - [Command API | PaperMC Docs](#command-api-papermc-docs) - [System properties | PaperMC Docs](#system-properties-papermc-docs) - [Tuning Velocity | PaperMC Docs](#tuning-velocity-papermc-docs) - [Creating your first plugin | PaperMC Docs](#creating-your-first-plugin-papermc-docs) - [Development | PaperMC Docs](#development-papermc-docs) - [Getting started | PaperMC Docs](#getting-started-papermc-docs) - [Administration | PaperMC Docs](#administration-papermc-docs) - [Events | PaperMC Docs](#events-papermc-docs) - [Contributing | PaperMC Docs](#contributing-papermc-docs) - [Adding plugins | PaperMC Docs](#adding-plugins-papermc-docs) - [Miscellaneous | PaperMC Docs](#miscellaneous-papermc-docs) - [Miscellaneous | PaperMC Docs](#miscellaneous-papermc-docs) - [Getting started | PaperMC Docs](#getting-started-papermc-docs) - [Inventories | PaperMC Docs](#inventories-papermc-docs) - [Lifecycle API | PaperMC Docs](#lifecycle-api-papermc-docs) - [How-to guides | PaperMC Docs](#how-to-guides-papermc-docs) - [Component API | PaperMC Docs](#component-api-papermc-docs) - [Minecraft-specific | PaperMC Docs](#minecraft-specific-papermc-docs) - [Aikar's flags | PaperMC Docs](#aikar-s-flags-papermc-docs) - [Reference | PaperMC Docs](#reference-papermc-docs) - [Entity API | PaperMC Docs](#entity-api-papermc-docs) - [Event API | PaperMC Docs](#event-api-papermc-docs) - [Configuring Anti-Xray | PaperMC Docs](#configuring-anti-xray-papermc-docs) - [Location | PaperMC Docs](#location-papermc-docs) - [Enums | PaperMC Docs](#enums-papermc-docs) - [Internationalization | PaperMC Docs](#internationalization-papermc-docs) - [Audiences | PaperMC Docs](#audiences-papermc-docs) - [Predicates | PaperMC Docs](#predicates-papermc-docs) - [Frequently asked questions | PaperMC Docs](#frequently-asked-questions-papermc-docs) - [Requirements | PaperMC Docs](#requirements-papermc-docs) - [commands.yml | PaperMC Docs](#commands-yml-papermc-docs) - [Custom events | PaperMC Docs](#custom-events-papermc-docs) - [Entities and players | PaperMC Docs](#entities-and-players-papermc-docs) - [Entity Pathfinder API | PaperMC Docs](#entity-pathfinder-api-papermc-docs) - [Handler lists | PaperMC Docs](#handler-lists-papermc-docs) - [permissions.yml | PaperMC Docs](#permissions-yml-papermc-docs) - [help.yml | PaperMC Docs](#help-yml-papermc-docs) - [Chat events | PaperMC Docs](#chat-events-papermc-docs) - [Adventure | PaperMC Docs](#adventure-papermc-docs) - [Registry | PaperMC Docs](#registry-papermc-docs) - [Debugging your plugin | PaperMC Docs](#debugging-your-plugin-papermc-docs) - [Suggestions | PaperMC Docs](#suggestions-papermc-docs) - [Teleportation | PaperMC Docs](#teleportation-papermc-docs) - [bukkit.yml | PaperMC Docs](#bukkit-yml-papermc-docs) - [Comparison | PaperMC Docs](#comparison-papermc-docs) - [Reading stacktraces | PaperMC Docs](#reading-stacktraces-papermc-docs) - [Listeners | PaperMC Docs](#listeners-papermc-docs) - [Migrating to or from Paper | PaperMC Docs](#migrating-to-or-from-paper-papermc-docs) - [Paper-specific | PaperMC Docs](#paper-specific-papermc-docs) - [Update checker | PaperMC Docs](#update-checker-papermc-docs) - [Lifecycle API | PaperMC Docs](#lifecycle-api-papermc-docs) - [Roadmap | PaperMC Docs](#roadmap-papermc-docs) - [Recipes | PaperMC Docs](#recipes-papermc-docs) - [Custom InventoryHolders | PaperMC Docs](#custom-inventoryholders-papermc-docs) - [Arguments | PaperMC Docs](#arguments-papermc-docs) - [Basics | PaperMC Docs](#basics-papermc-docs) - [Supporting Paper and Folia | PaperMC Docs](#supporting-paper-and-folia-papermc-docs) - [Miscellaneous | PaperMC Docs](#miscellaneous-papermc-docs) - [Executors | PaperMC Docs](#executors-papermc-docs) - [Minecraft internals | PaperMC Docs](#minecraft-internals-papermc-docs) - [Signed messages | PaperMC Docs](#signed-messages-papermc-docs) - [Mob Goal API | PaperMC Docs](#mob-goal-api-papermc-docs) - [Custom arguments | PaperMC Docs](#custom-arguments-papermc-docs) - [Basic troubleshooting | PaperMC Docs](#basic-troubleshooting-papermc-docs) - [Profiling | PaperMC Docs](#profiling-papermc-docs) - [Data components | PaperMC Docs](#data-components-papermc-docs) - [Getting started | PaperMC Docs](#getting-started-papermc-docs) - [Registration | PaperMC Docs](#registration-papermc-docs) - [Command trees | PaperMC Docs](#command-trees-papermc-docs) - [Vanilla data files | PaperMC Docs](#vanilla-data-files-papermc-docs) - [Menu Type API | PaperMC Docs](#menu-type-api-papermc-docs) - [CLI Arguments | PaperMC Docs](#cli-arguments-papermc-docs) - [Bug fixes | PaperMC Docs](#bug-fixes-papermc-docs) - [Paper plugins | PaperMC Docs](#paper-plugins-papermc-docs) - [Paper plugins | PaperMC Docs](#paper-plugins-papermc-docs) - [Display entities | PaperMC Docs](#display-entities-papermc-docs) - [Persistent data container (PDC) | PaperMC Docs](#persistent-data-container-pdc-papermc-docs) - [paperweight-userdev | PaperMC Docs](#paperweight-userdev-papermc-docs) - [Scheduling | PaperMC Docs](#scheduling-papermc-docs) - [server.properties | PaperMC Docs](#server-properties-papermc-docs) - [Plugin messaging | PaperMC Docs](#plugin-messaging-papermc-docs) - [Updating | PaperMC Docs](#updating-papermc-docs) - [How plugins work | PaperMC Docs](#how-plugins-work-papermc-docs) - [Plugin configuration | PaperMC Docs](#plugin-configuration-papermc-docs) - [Using databases | PaperMC Docs](#using-databases-papermc-docs) - [Next steps | PaperMC Docs](#next-steps-papermc-docs) - [Arguments and literals | PaperMC Docs](#arguments-and-literals-papermc-docs) - [Introduction | PaperMC Docs](#introduction-papermc-docs) - [Datapack discovery | PaperMC Docs](#datapack-discovery-papermc-docs) - [plugin.yml | PaperMC Docs](#plugin-yml-papermc-docs) - [Project setup | PaperMC Docs](#project-setup-papermc-docs) - [Global configuration | PaperMC Docs](#global-configuration-papermc-docs) - [Permissions | PaperMC Docs](#permissions-papermc-docs) - [Vanilla-like experience | PaperMC Docs](#vanilla-like-experience-papermc-docs) - [Basic commands | PaperMC Docs](#basic-commands-papermc-docs) - [Registries | PaperMC Docs](#registries-papermc-docs) - [Dialog API | PaperMC Docs](#dialog-api-papermc-docs) - [Commands | PaperMC Docs](#commands-papermc-docs) - [spigot.yml | PaperMC Docs](#spigot-yml-papermc-docs) - [Getting started | PaperMC Docs](#getting-started-papermc-docs) - [System properties | PaperMC Docs](#system-properties-papermc-docs) - [World configuration | PaperMC Docs](#world-configuration-papermc-docs) - [Introduction | PaperMC Docs](#introduction-papermc-docs) - [Particles | PaperMC Docs](#particles-papermc-docs) - [API | PaperMC Docs](#api-papermc-docs) - [Administration | PaperMC Docs](#administration-papermc-docs) - [Configuration | PaperMC Docs](#configuration-papermc-docs) - [Command API | PaperMC Docs](#command-api-papermc-docs) - [Development | PaperMC Docs](#development-papermc-docs) --- # Paper Documentation | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/#_top) Paper Documentation =================== Paper is a Minecraft: Java Edition game server, designed to greatly improve performance and offer more advanced features and API. [Administration](https://docs.papermc.io/paper/admin) Information and tutorials regarding the administration of a Paper server. [Development](https://docs.papermc.io/paper/dev) Information and tutorials for developers on how to create and expand on Paper plugins. [Contributing](https://docs.papermc.io/paper/contributing) Information and tutorials for developers wishing to contribute to the Paper project. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Welcome | PaperMC Docs [Skip to content](https://docs.papermc.io/#_top) ![PaperMC Logo](https://docs.papermc.io/_astro/papermc_logo.min_19r4d2.svg) PaperMC Docs ============ Documentation for all projects under the PaperMC umbrella, including Paper, Velocity and Folia. [Paper\ \ High performance Minecraft server that aims to fix gameplay and mechanics inconsistencies.](https://docs.papermc.io/paper) [Velocity\ \ The modern, next-generation Minecraft server proxy.](https://docs.papermc.io/velocity) [Folia\ \ A fork of Paper which adds regionized multithreading to the dedicated server.](https://docs.papermc.io/folia) [Adventure\ \ A Java library for server-controllable user interface elements in Minecraft: Java Edition.](https://docs.papermc.io/adventure) [Waterfall\ \ A discontinued BungeeCord proxy fork that aimed to improve performance and stability.](https://docs.papermc.io/waterfall) [Miscellaneous\ \ Various other documentation and tools.](https://docs.papermc.io/misc) [Contribute](https://github.com/PaperMC/docs) ---------------------------------------------- [Section titled “Contribute”](https://docs.papermc.io/#contribute) We’d like to extend a warm thank you to all the contributors who have helped bring this documentation site to life. Whether you’ve written code, submitted feedback, fixed a typo, or shared your expertise - every contribution is deeply appreciated. This is very much a team effort, and we’re grateful to have you with us on the journey! * [![zlataovce](https://avatars.githubusercontent.com/u/34477304?s=64 "zlataovce")](https://github.com/zlataovce) * [![olijeffers0n](https://avatars.githubusercontent.com/u/69084614?s=64 "olijeffers0n")](https://github.com/olijeffers0n) * [![e-im](https://avatars.githubusercontent.com/u/76139600?s=64 "e-im")](https://github.com/e-im) * [![Strokkur424](https://avatars.githubusercontent.com/u/133226102?s=64 "Strokkur424")](https://github.com/Strokkur424) * [![kashike](https://avatars.githubusercontent.com/u/5474071?s=64 "kashike")](https://github.com/kashike) * [![Doc94](https://avatars.githubusercontent.com/u/3602279?s=64 "Doc94")](https://github.com/Doc94) * [![powercasgamer](https://avatars.githubusercontent.com/u/40437205?s=64 "powercasgamer")](https://github.com/powercasgamer) * [![Machine-Maker](https://avatars.githubusercontent.com/u/15055071?s=64 "Machine-Maker")](https://github.com/Machine-Maker) * [![4drian3d](https://avatars.githubusercontent.com/u/68704415?s=64 "4drian3d")](https://github.com/4drian3d) * [![lynxplay](https://avatars.githubusercontent.com/u/32834385?s=64 "lynxplay")](https://github.com/lynxplay) * [![Lulu13022002](https://avatars.githubusercontent.com/u/41980282?s=64 "Lulu13022002")](https://github.com/Lulu13022002) * [![Warriorrrr](https://avatars.githubusercontent.com/u/50800980?s=64 "Warriorrrr")](https://github.com/Warriorrrr) * [![kennytv](https://avatars.githubusercontent.com/u/28825609?s=64 "kennytv")](https://github.com/kennytv) * [![MiniDigger](https://avatars.githubusercontent.com/u/2185527?s=64 "MiniDigger")](https://github.com/MiniDigger) * [![Timongcraft](https://avatars.githubusercontent.com/u/77288029?s=64 "Timongcraft")](https://github.com/Timongcraft) * [![Leguan16](https://avatars.githubusercontent.com/u/59799222?s=64 "Leguan16")](https://github.com/Leguan16) * [![456dev](https://avatars.githubusercontent.com/u/42748092?s=64 "456dev")](https://github.com/456dev) * [![NoahvdAa](https://avatars.githubusercontent.com/u/44026893?s=64 "NoahvdAa")](https://github.com/NoahvdAa) * [![Owen1212055](https://avatars.githubusercontent.com/u/23108066?s=64 "Owen1212055")](https://github.com/Owen1212055) * [![renovate[bot]](https://avatars.githubusercontent.com/u/29139614?s=64 "renovate[bot]")](https://github.com/renovate[bot]) * [![Nacioszeczek](https://avatars.githubusercontent.com/u/41339226?s=64 "Nacioszeczek")](https://github.com/Nacioszeczek) * [![notTamion](https://avatars.githubusercontent.com/u/70228790?s=64 "notTamion")](https://github.com/notTamion) * [![Privatech38](https://avatars.githubusercontent.com/u/99482159?s=64 "Privatech38")](https://github.com/Privatech38) * [![Phoenix616](https://avatars.githubusercontent.com/u/5768781?s=64 "Phoenix616")](https://github.com/Phoenix616) * [![kezz](https://avatars.githubusercontent.com/u/1526243?s=64 "kezz")](https://github.com/kezz) * [![mja00](https://avatars.githubusercontent.com/u/11252574?s=64 "mja00")](https://github.com/mja00) * [![granny](https://avatars.githubusercontent.com/u/43185817?s=64 "granny")](https://github.com/granny) * [![stonar96](https://avatars.githubusercontent.com/u/18699205?s=64 "stonar96")](https://github.com/stonar96) * [![electronicboy](https://avatars.githubusercontent.com/u/1228900?s=64 "electronicboy")](https://github.com/electronicboy) * [![jpenilla](https://avatars.githubusercontent.com/u/11360596?s=64 "jpenilla")](https://github.com/jpenilla) * [![sowelipililimute](https://avatars.githubusercontent.com/u/20326855?s=64 "sowelipililimute")](https://github.com/sowelipililimute) * [![TetraTheta](https://avatars.githubusercontent.com/u/37061801?s=64 "TetraTheta")](https://github.com/TetraTheta) * [![Toffikk](https://avatars.githubusercontent.com/u/62406295?s=64 "Toffikk")](https://github.com/Toffikk) * [![Hinterhaeltiger](https://avatars.githubusercontent.com/u/76826310?s=64 "Hinterhaeltiger")](https://github.com/Hinterhaeltiger) * [![NonSwag](https://avatars.githubusercontent.com/u/54660361?s=64 "NonSwag")](https://github.com/NonSwag) * [![jacklak-redstone](https://avatars.githubusercontent.com/u/176782468?s=64 "jacklak-redstone")](https://github.com/jacklak-redstone) * [![enten](https://avatars.githubusercontent.com/u/977713?s=64 "enten")](https://github.com/enten) * [![PetarMc1](https://avatars.githubusercontent.com/u/160483025?s=64 "PetarMc1")](https://github.com/PetarMc1) * [![darbyjack](https://avatars.githubusercontent.com/u/21014720?s=64 "darbyjack")](https://github.com/darbyjack) * [![CyberFlameGO](https://avatars.githubusercontent.com/u/24910512?s=64 "CyberFlameGO")](https://github.com/CyberFlameGO) * [![Cubicake](https://avatars.githubusercontent.com/u/70577278?s=64 "Cubicake")](https://github.com/Cubicake) * [![RealBauHD](https://avatars.githubusercontent.com/u/71191102?s=64 "RealBauHD")](https://github.com/RealBauHD) * [![A248](https://avatars.githubusercontent.com/u/22414680?s=64 "A248")](https://github.com/A248) * [![samrussell](https://avatars.githubusercontent.com/u/1481279?s=64 "samrussell")](https://github.com/samrussell) * [![sh-cho](https://avatars.githubusercontent.com/u/11611397?s=64 "sh-cho")](https://github.com/sh-cho) * [![ShaneBeee](https://avatars.githubusercontent.com/u/20008482?s=64 "ShaneBeee")](https://github.com/ShaneBeee) * [![Siebrenvde](https://avatars.githubusercontent.com/u/13187218?s=64 "Siebrenvde")](https://github.com/Siebrenvde) * [![SpaceWalkerRS](https://avatars.githubusercontent.com/u/48224626?s=64 "SpaceWalkerRS")](https://github.com/SpaceWalkerRS) * [![SplotyCode](https://avatars.githubusercontent.com/u/31861387?s=64 "SplotyCode")](https://github.com/SplotyCode) * [![Spottedleaf](https://avatars.githubusercontent.com/u/6100722?s=64 "Spottedleaf")](https://github.com/Spottedleaf) * [![drk1rd](https://avatars.githubusercontent.com/u/58465650?s=64 "drk1rd")](https://github.com/drk1rd) * [![Syrent](https://avatars.githubusercontent.com/u/56670179?s=64 "Syrent")](https://github.com/Syrent) * [![szymon-off](https://avatars.githubusercontent.com/u/94014682?s=64 "szymon-off")](https://github.com/szymon-off) * [![Biquaternions](https://avatars.githubusercontent.com/u/11415969?s=64 "Biquaternions")](https://github.com/Biquaternions) * [![RandomTNT](https://avatars.githubusercontent.com/u/53399258?s=64 "RandomTNT")](https://github.com/RandomTNT) * [![RalphORama](https://avatars.githubusercontent.com/u/6566104?s=64 "RalphORama")](https://github.com/RalphORama) * [![Potothingi](https://avatars.githubusercontent.com/u/108602622?s=64 "Potothingi")](https://github.com/Potothingi) * [![octylFractal](https://avatars.githubusercontent.com/u/2093023?s=64 "octylFractal")](https://github.com/octylFractal) * [![7rebux](https://avatars.githubusercontent.com/u/58339645?s=64 "7rebux")](https://github.com/7rebux) * [![Nicheven](https://avatars.githubusercontent.com/u/134471955?s=64 "Nicheven")](https://github.com/Nicheven) * [![Natfan](https://avatars.githubusercontent.com/u/6197998?s=64 "Natfan")](https://github.com/Natfan) * [![xMrAfonso](https://avatars.githubusercontent.com/u/44532605?s=64 "xMrAfonso")](https://github.com/xMrAfonso) * [![minacle](https://avatars.githubusercontent.com/u/2531397?s=64 "minacle")](https://github.com/minacle) * [![clrxbl](https://avatars.githubusercontent.com/u/28601081?s=64 "clrxbl")](https://github.com/clrxbl) * [![Sytm](https://avatars.githubusercontent.com/u/21055143?s=64 "Sytm")](https://github.com/Sytm) * [![ikifar2012](https://avatars.githubusercontent.com/u/20800434?s=64 "ikifar2012")](https://github.com/ikifar2012) * [![zml2008](https://avatars.githubusercontent.com/u/629092?s=64 "zml2008")](https://github.com/zml2008) * [![tgbhy](https://avatars.githubusercontent.com/u/81264732?s=64 "tgbhy")](https://github.com/tgbhy) * [![2sweetheart2](https://avatars.githubusercontent.com/u/69629490?s=64 "2sweetheart2")](https://github.com/2sweetheart2) * [![supercoolspy](https://avatars.githubusercontent.com/u/66487448?s=64 "supercoolspy")](https://github.com/supercoolspy) * [![poikcue](https://avatars.githubusercontent.com/u/65440607?s=64 "poikcue")](https://github.com/poikcue) * [![pairnon](https://avatars.githubusercontent.com/u/123353727?s=64 "pairnon")](https://github.com/pairnon) * [![kokiriglade](https://avatars.githubusercontent.com/u/60290002?s=64 "kokiriglade")](https://github.com/kokiriglade) * [![jamespglines](https://avatars.githubusercontent.com/u/28969320?s=64 "jamespglines")](https://github.com/jamespglines) * [![0xdeepz](https://avatars.githubusercontent.com/u/97910694?s=64 "0xdeepz")](https://github.com/0xdeepz) * [![caio0452](https://avatars.githubusercontent.com/u/159462011?s=64 "caio0452")](https://github.com/caio0452) * [![novitpw](https://avatars.githubusercontent.com/u/90355736?s=64 "novitpw")](https://github.com/novitpw) * [![Zoriot](https://avatars.githubusercontent.com/u/59896907?s=64 "Zoriot")](https://github.com/Zoriot) * [![YouHaveTrouble](https://avatars.githubusercontent.com/u/6951472?s=64 "YouHaveTrouble")](https://github.com/YouHaveTrouble) * [![Wuason6x9](https://avatars.githubusercontent.com/u/85463958?s=64 "Wuason6x9")](https://github.com/Wuason6x9) * [![wikmor](https://avatars.githubusercontent.com/u/100677740?s=64 "wikmor")](https://github.com/wikmor) * [![szepeviktor](https://avatars.githubusercontent.com/u/952007?s=64 "szepeviktor")](https://github.com/szepeviktor) * [![voidpointer0x00](https://avatars.githubusercontent.com/u/43143315?s=64 "voidpointer0x00")](https://github.com/voidpointer0x00) * [![vadcx](https://avatars.githubusercontent.com/u/129969897?s=64 "vadcx")](https://github.com/vadcx) * [![tlm9201](https://avatars.githubusercontent.com/u/69724732?s=64 "tlm9201")](https://github.com/tlm9201) * [![thorbm1500](https://avatars.githubusercontent.com/u/43374833?s=64 "thorbm1500")](https://github.com/thorbm1500) * [![TheBjoRedCraft](https://avatars.githubusercontent.com/u/143264463?s=64 "TheBjoRedCraft")](https://github.com/TheBjoRedCraft) * [![TankObliterator](https://avatars.githubusercontent.com/u/129139958?s=64 "TankObliterator")](https://github.com/TankObliterator) * [![tangjin0418](https://avatars.githubusercontent.com/u/55261514?s=64 "tangjin0418")](https://github.com/tangjin0418) * [![fabianmakila](https://avatars.githubusercontent.com/u/44451855?s=64 "fabianmakila")](https://github.com/fabianmakila) * [![evan-goode](https://avatars.githubusercontent.com/u/7495216?s=64 "evan-goode")](https://github.com/evan-goode) * [![florianreuth](https://avatars.githubusercontent.com/u/60033407?s=64 "florianreuth")](https://github.com/florianreuth) * [![NicoNekoDev](https://avatars.githubusercontent.com/u/13527191?s=64 "NicoNekoDev")](https://github.com/NicoNekoDev) * [![Djaytan](https://avatars.githubusercontent.com/u/26904516?s=64 "Djaytan")](https://github.com/Djaytan) * [![diogotcorreia](https://avatars.githubusercontent.com/u/7467891?s=64 "diogotcorreia")](https://github.com/diogotcorreia) * [![DereC4](https://avatars.githubusercontent.com/u/53978637?s=64 "DereC4")](https://github.com/DereC4) * [![DerEchtePilz](https://avatars.githubusercontent.com/u/81232921?s=64 "DerEchtePilz")](https://github.com/DerEchtePilz) * [![davidjpfeiffer](https://avatars.githubusercontent.com/u/8846738?s=64 "davidjpfeiffer")](https://github.com/davidjpfeiffer) * [![samuelask](https://avatars.githubusercontent.com/u/77889313?s=64 "samuelask")](https://github.com/samuelask) * [![AdrianGonz97](https://avatars.githubusercontent.com/u/31664583?s=64 "AdrianGonz97")](https://github.com/AdrianGonz97) * [![Chamogelastos](https://avatars.githubusercontent.com/u/150929858?s=64 "Chamogelastos")](https://github.com/Chamogelastos) * [![benwoo1110](https://avatars.githubusercontent.com/u/30431861?s=64 "benwoo1110")](https://github.com/benwoo1110) * [![Badbird5907](https://avatars.githubusercontent.com/u/50347938?s=64 "Badbird5907")](https://github.com/Badbird5907) * [![BaconCat1](https://avatars.githubusercontent.com/u/126538523?s=64 "BaconCat1")](https://github.com/BaconCat1) * [![BBaoVanC](https://avatars.githubusercontent.com/u/17971474?s=64 "BBaoVanC")](https://github.com/BBaoVanC) * [![Axodouble](https://avatars.githubusercontent.com/u/53979495?s=64 "Axodouble")](https://github.com/Axodouble) * [![ArikSquad](https://avatars.githubusercontent.com/u/75741608?s=64 "ArikSquad")](https://github.com/ArikSquad) * [![astei](https://avatars.githubusercontent.com/u/16436212?s=64 "astei")](https://github.com/astei) * [![DrakePork](https://avatars.githubusercontent.com/u/29175884?s=64 "DrakePork")](https://github.com/DrakePork) * [![Andre601](https://avatars.githubusercontent.com/u/11576465?s=64 "Andre601")](https://github.com/Andre601) * [![NotMyFault](https://avatars.githubusercontent.com/u/13383509?s=64 "NotMyFault")](https://github.com/NotMyFault) * [![CatTeaA](https://avatars.githubusercontent.com/u/135555687?s=64 "CatTeaA")](https://github.com/CatTeaA) * [![m4sc0](https://avatars.githubusercontent.com/u/73311544?s=64 "m4sc0")](https://github.com/m4sc0) * [![Malfrador](https://avatars.githubusercontent.com/u/6106558?s=64 "Malfrador")](https://github.com/Malfrador) * [![Makonede](https://avatars.githubusercontent.com/u/61922615?s=64 "Makonede")](https://github.com/Makonede) * [![MC-XiaoHei](https://avatars.githubusercontent.com/u/100807593?s=64 "MC-XiaoHei")](https://github.com/MC-XiaoHei) * [![lucien-n](https://avatars.githubusercontent.com/u/77048269?s=64 "lucien-n")](https://github.com/lucien-n) * [![CodingWithAnxiety](https://avatars.githubusercontent.com/u/78890450?s=64 "CodingWithAnxiety")](https://github.com/CodingWithAnxiety) * [![codeHusky](https://avatars.githubusercontent.com/u/6946558?s=64 "codeHusky")](https://github.com/codeHusky) * [![LittleChest](https://avatars.githubusercontent.com/u/81231195?s=64 "LittleChest")](https://github.com/LittleChest) * [![rainbowdashlabs](https://avatars.githubusercontent.com/u/46890129?s=64 "rainbowdashlabs")](https://github.com/rainbowdashlabs) * [![tech-6](https://avatars.githubusercontent.com/u/28657673?s=64 "tech-6")](https://github.com/tech-6) * [![KastenKlicker](https://avatars.githubusercontent.com/u/63316173?s=64 "KastenKlicker")](https://github.com/KastenKlicker) * [![Kamillaova](https://avatars.githubusercontent.com/u/54859825?s=64 "Kamillaova")](https://github.com/Kamillaova) * [![webcrawls](https://avatars.githubusercontent.com/u/69081152?s=64 "webcrawls")](https://github.com/webcrawls) * [![ThatGuyJustin](https://avatars.githubusercontent.com/u/14909116?s=64 "ThatGuyJustin")](https://github.com/ThatGuyJustin) * [![illuminator3](https://avatars.githubusercontent.com/u/48388251?s=64 "illuminator3")](https://github.com/illuminator3) * [![JavierFlores09](https://avatars.githubusercontent.com/u/113814758?s=64 "JavierFlores09")](https://github.com/JavierFlores09) * [![jacky8399](https://avatars.githubusercontent.com/u/7542810?s=64 "jacky8399")](https://github.com/jacky8399) * [![ItsJustMiaouss](https://avatars.githubusercontent.com/u/59478524?s=64 "ItsJustMiaouss")](https://github.com/ItsJustMiaouss) * [![NinjaMandalorian](https://avatars.githubusercontent.com/u/26630126?s=64 "NinjaMandalorian")](https://github.com/NinjaMandalorian) * [![ilgrandeanonimo](https://avatars.githubusercontent.com/u/65458792?s=64 "ilgrandeanonimo")](https://github.com/ilgrandeanonimo) * [![HexedHero](https://avatars.githubusercontent.com/u/6012891?s=64 "HexedHero")](https://github.com/HexedHero) * [![Hallo5000](https://avatars.githubusercontent.com/u/59452026?s=64 "Hallo5000")](https://github.com/Hallo5000) * [![Flix3r](https://avatars.githubusercontent.com/u/73292441?s=64 "Flix3r")](https://github.com/Flix3r) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Adventure | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/#_top) Adventure ========= Documentation for Adventure and its many libraries. [Getting started](https://docs.papermc.io/adventure/getting-started) A guide to getting started with Adventure. [Community libraries](https://docs.papermc.io/adventure/community-libraries) Libraries utilizing the Adventure API. [FAQ](https://docs.papermc.io/adventure/faq) Frequently asked questions. [Audiences](https://docs.papermc.io/adventure/audiences) A guide to Adventure Audiences. [Text (Chat Components)](https://docs.papermc.io/adventure/text) Everything you need to know about Components. [🗃️ Text serializers](https://docs.papermc.io/adventure/serializer) Everything to know about text/component serializers. [🗃️ MiniMessage](https://docs.papermc.io/adventure/minimessage) Documentation regarding MiniMessage. [Boss bars](https://docs.papermc.io/adventure/bossbar) A guide to Adventure BossBars. [Sound](https://docs.papermc.io/adventure/sound) A guide to playing sound with Adventure. [Titles](https://docs.papermc.io/adventure/titles) Displaying titles to players. [Books](https://docs.papermc.io/adventure/book) A guide to Adventure Books. [Player list/Tab list](https://docs.papermc.io/adventure/tablist) Setting the player list with Adventure. [Resource packs](https://docs.papermc.io/adventure/resource-pack) A guide to using resource packs with Adventure. [Localization](https://docs.papermc.io/adventure/localization) Utilizing localization in Adventure. [🗃️ Platforms](https://docs.papermc.io/adventure/platform) Documentation regarding various implementations of the Adventure API. [🗃️ Version history](https://docs.papermc.io/adventure/version-history) Pages dedicated to displaying the latest changelogs! [🗃️ Migration](https://docs.papermc.io/adventure/migration) Moving to the latest Adventure version. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Audiences | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/audiences/#_top) Audiences ========= An audience, at its core, is a grouping of 0 or more viewers of some content. The concept of an audience is where Adventure makes its most clear break from other Minecraft platforms. As an API, `Audience` is designed to be a universal interface for any player, command sender, console, or otherwise who can receive text, titles, boss bars, and other Minecraft media. This allows extending audiences to cover more than one individual receiver - possible “audiences” could include a team, server, world, or all players that satisfy some predicate (such as having a certain permission). The universal interface also allows reducing boilerplate by gracefully degrading functionality if it is not applicable. For instance, it does not make much sense to send a boss bar to a command sender, and you can’t send titles to Minecraft 1.7 clients. You will normally get audience instances from one of the [Platforms](https://docs.papermc.io/adventure/platform) . The Adventure API includes two audience implementations itself: one that does not support any action (and thus does nothing). `Audience.empty()`, and one that forwards an action to each member in the audience, `Audience.audience()` and related methods, along with the `ForwardingAudience` that implements the forwarding logic for you. Most users using will primarily use this API to show content created by other parts of the API. Pointers -------- [Section titled “Pointers”](https://docs.papermc.io/adventure/audiences/#pointers) Audiences can also provide arbitrary information, such as display name or UUID. This is done using the pointer system. Examples: // get the uuid from an audience member, returning an Optionalaudience.get(Identity.UUID); // get the display name, returning a defaultaudience.getOrDefault(Identity.DISPLAY_NAME, Component.text("no display name!")); Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Books | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/book/#_top) Books ===== Constructing a Book ------------------- [Section titled “Constructing a Book”](https://docs.papermc.io/adventure/book/#constructing-a-book) Books are composed of: * A component used for the title of the book * A component used for the author of the book * A collection of components used for the book pages **Example:** // Create and open a book about cats for the target audiencepublic void openMyBook(final @NonNull Audience target) { Component bookTitle = Component.text("Encyclopedia of cats"); Component bookAuthor = Component.text("kashike"); Collection bookPages = Cats.getCatKnowledge(); Book myBook = Book.book(bookTitle, bookAuthor, bookPages); target.openBook(myBook);} Extra info regarding Books -------------------------- [Section titled “Extra info regarding Books”](https://docs.papermc.io/adventure/book/#extra-info-regarding-books) Books in adventure are not necessarily connected to an interactable book item in the client. As of the current release such a connection needs to be implemented outside of adventure. Any component that surpasses the game limit for text per page will be truncated client side, the same applies to the amount of components (pages). Further reading about these limits can be done at the [Minecraft Wiki](https://minecraft.wiki/w/Book_and_Quill#Writing) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Community libraries | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/community-libraries/#_top) Community libraries =================== Adventure aims to provide the core libraries needed for interacting with chat components. However, with the limited resources and time of the Adventure team and the sheer number of possible use cases, we can’t hope to provide direct solutions for every problem. Luckily, many of our community members have produced libraries that complement Adventure, providing additional features and integrations with other software. Serializers ----------- [Section titled “Serializers”](https://docs.papermc.io/adventure/community-libraries/#serializers) These are libraries focused around providing additional serialization formats for chat components. They typically have no dependencies on a specific platform, just Adventure and potentially a library with which they integrate. | Name | Description | Link | | --- | --- | --- | | EnhancedLegacyText | Alternative input format that is legacy compatible with new features | [Vankka/EnhancedLegacyText](https://github.com/Vankka/EnhancedLegacyText) | | MCDiscordReserializer | Serializers for going between Minecraft & Discord | [Vankka/MCDiscordReserializer](https://github.com/Vankka/MCDiscordReserializer) | | Minedown | A markdown-style format for representing components | [Phoenix616/MineDown](https://github.com/Phoenix616/MineDown) | Platforms --------- [Section titled “Platforms”](https://docs.papermc.io/adventure/community-libraries/#platforms) These are libraries that provide implementations of Adventure on different platforms that aren’t officially integrated into the software or maintained by the Adventure team. | Name | Description | Link | | --- | --- | --- | | adventure-platform-hytale | Adventure platform implementation for Hytale | [ArikSquad/adventure-platform-hytale](https://github.com/ArikSquad/adventure-platform-hytale) | Expansions ---------- [Section titled “Expansions”](https://docs.papermc.io/adventure/community-libraries/#expansions) These are libraries that expand upon the core Adventure API, providing platform-agnostic additions that are not included or not suitable for inclusion in the main project. | Name | Description | Link | | --- | --- | --- | | MiniPlaceholders | A platform-agnostic MiniMessage Component-based Placeholders library | [MiniPlaceholders/MiniPlaceholders](https://github.com/MiniPlaceholders/MiniPlaceholders) | Additional user interface libraries ----------------------------------- [Section titled “Additional user interface libraries”](https://docs.papermc.io/adventure/community-libraries/#additional-user-interface-libraries) These are libraries with a focus on something other than chat components, that use Adventure in their API. They provide support for using Adventure in user interface elements not supported by the core Adventure libraries. This includes, but is not limited to, commands, scoreboards, and inventories. These libraries will often depend on one or more specific platforms to support their functionality. | Name | Description | Link | | --- | --- | --- | | Cloud | A general-purpose Java command dispatcher & framework | [Incendo/cloud](https://github.com/Incendo/cloud) | | Creative | A resource-pack library for Minecraft: Java Edition | [unnamed/creative](https://github.com/unnamed/creative) | | Inventory Framework | An inventory framework for managing GUIs | [stefvanschie/IF](https://github.com/stefvanschie/IF) | | LiteCommands | A annotation based command framework for Velocity, Bukkit, BungeeCord | [Rollczi/LiteCommands](https://github.com/Rollczi/LiteCommands) | | ProtocolSidebar | An easy to use sidebar library for Paper/Spigot servers | [CatCoderr/ProtocolSidebar](https://github.com/CatCoderr/ProtocolSidebar) | | ScoreboardLibrary | A scoreboard library for Paper/Spigot servers | [MegavexNetwork/scoreboard-library](https://github.com/MegavexNetwork/scoreboard-library) | | Triumph GUI | A library made to simplify the creation of inventory GUIs | [TriumphTeam/triumph-gui](https://github.com/TriumphTeam/triumph-gui) | Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Folia Documentation | PaperMC Docs [Skip to content](https://docs.papermc.io/folia/#_top) Folia Documentation =================== Folia is a fork of Paper which adds regionized multithreading to the dedicated server. [Administration](https://docs.papermc.io/folia/admin) Information and tutorials regarding the administration of a Folia server. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Boss bars | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/bossbar/#_top) Boss bars ========= Constructing a BossBar ---------------------- [Section titled “Constructing a BossBar”](https://docs.papermc.io/adventure/bossbar/#constructing-a-bossbar) Boss Bars are composed of: * A component used for the title of the boss bar * A number from 0 to 1 used to determine how full the boss bar should be * A color, will be downsampled for clients <1.9 * An overlay that determines the amount of visual segments on the boss bar **Examples:** private @Nullable BossBar activeBar; public void showMyBossBar(final @NonNull Audience target) { final Component name = Component.text("Awesome BossBar"); // Creates a red boss bar which has no progress and no notches final BossBar emptyBar = BossBar.bossBar(name, 0, BossBar.Color.RED, BossBar.Overlay.PROGRESS); // Creates a green boss bar which has 50% progress and 10 notches final BossBar halfBar = BossBar.bossBar(name, 0.5f, BossBar.Color.GREEN, BossBar.Overlay.NOTCHED_10); // etc.. final BossBar fullBar = BossBar.bossBar(name, 1, BossBar.Color.BLUE, BossBar.Overlay.NOTCHED_20); // Send a bossbar to your audience target.showBossBar(fullBar); // Store it locally to be able to hide it manually later this.activeBar = fullBar;} public void hideActiveBossBar(final @NonNull Audience target) { target.hideBossBar(this.activeBar); this.activeBar = null;} Changing an active BossBar -------------------------- [Section titled “Changing an active BossBar”](https://docs.papermc.io/adventure/bossbar/#changing-an-active-bossbar) Boss bars are mutable and listen for changes on their object, the in-game view will change automatically without having to manually refresh it! Therefore, if this boss bar is currently active final BossBar bossBar = BossBar.bossBar(Component.text("Cat counter"), 0, BossBar.Color.RED, BossBar.Overlay.PROGRESS); and `BossBar.name()` with a component is called final Component newText = Component.text("Duck counter");bossBar.name(newText); the boss bar will be updated automatically. The same thing goes for `progress`, `color` and `overlay`. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # FAQ | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/faq/#_top) FAQ === We find that there are some issues users come across relatively frequently while applying the Adventure library in certain contexts. These may not be directly related to Adventure itself, but these answers are published here those that ask them: Why is my lore in italics? -------------------------- [Section titled “Why is my lore in italics?”](https://docs.papermc.io/adventure/faq/#why-is-my-lore-in-italics) Components will inherit style from their parent. For example, in the following code snippet, each word will be red, despite red not being explicitly set on the appended component: `text("hi", RED).append(text("also red!"))`. In vanilla Minecraft, some places where components are rendered have parent styles. For example, lore text has a parent style that makes all text italic. This means that you will need to set italic to false if you do not want any component you are storing in lore to be italic. The `Component.decorationIfAbsent()` method can apply this to existing components without overriding any formatting specifically set by users. Messages not sending? Hex colors not working? Events not appearing? Fonts messed up? ------------------------------------------------------------------------------------ [Section titled “Messages not sending? Hex colors not working? Events not appearing? Fonts messed up?”](https://docs.papermc.io/adventure/faq/#messages-not-sending-hex-colors-not-working-events-not-appearing-fonts-messed-up) * Test on a vanilla client, without any mods or resource packs. Modded clients (such as Badlion), client mods, and even resource packs can break many elements of the modern JSON chat format and mess with incoming chat packets in ways that cause a myriad of issues. * Try without other plugins/mods. If another plugin/mod is modifying outgoing packets or formatting chat messages, this could cause a loss of formatting in the messages you send. Try without any other plugins to see if any are causing issues. * For RGB colors, test on a client of at least version _1.16_. Mojang added RGB support in this version. The JSON message format has evolved over time and has had many new additions since its introduction many, many years ago. For a full version history, see [the Minecraft wiki](https://minecraft.wiki/w/Text_component_format) . How can I support both MiniMessage and legacy (§-code) formatting? ------------------------------------------------------------------ [Section titled “How can I support both MiniMessage and legacy (§-code) formatting?”](https://docs.papermc.io/adventure/faq/#how-can-i-support-both-minimessage-and-legacy--code-formatting) If you have legacy in configuration files, or other places, it is suggested that you migrate them once using the legacy deserializer to turn them into a component and then MiniMessage to serialize them into proper MiniMessage format. There are no working, recommended, or supported ways of using both MiniMessage and legacy color codes and there never will be. Even simple find-and-replace style techniques do not work and will fail to take into account the quirks of style resetting in legacy formatting. How can I use Bukkit’s PlaceholderAPI in MiniMessage messages? -------------------------------------------------------------- [Section titled “How can I use Bukkit’s PlaceholderAPI in MiniMessage messages?”](https://docs.papermc.io/adventure/faq/#how-can-i-use-bukkits-placeholderapi-in-minimessage-messages) PlaceholderAPI placeholders are not supported in MiniMessage. However, you can easily create a custom tag resolver that can allow users to use PlaceholderAPI placeholders in MiniMessage strings, like in the following example: Example Example method to create a MiniMessage placeholder that parses PlaceholderAPI placeholders for a player. The tag added is of the format ``. For example, ``. Credit to `mbaxter`. /*** Creates a tag resolver capable of resolving PlaceholderAPI tags for a given player.** @param player the player* @return the tag resolver*/public @NotNull TagResolver papiTag(final @NotNull Player player) { return TagResolver.resolver("papi", (argumentQueue, context) -> { // Get the string placeholder that they want to use. final String papiPlaceholder = argumentQueue.popOr("papi tag requires an argument").value(); // Then get PAPI to parse the placeholder for the given player. final String parsedPlaceholder = PlaceholderAPI.setPlaceholders(player, '%' + papiPlaceholder + '%'); // We need to turn this ugly legacy string into a nice component. final Component componentPlaceholder = LegacyComponentSerializer.legacySection().deserialize(parsedPlaceholder); // Finally, return the tag instance to insert the placeholder! return Tag.selfClosingInserting(componentPlaceholder); });} Why am I getting a `NoSuchFieldError`, `NoSuchMethodError`, `ClassNotFoundException` or similar when updating/using `adventure-platform-*`, `adventure-text-minimessage`, `adventure-api` or other related libraries/tools? --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [Section titled “Why am I getting a NoSuchFieldError, NoSuchMethodError, ClassNotFoundException or similar when updating/using adventure-platform-\*, adventure-text-minimessage, adventure-api or other related libraries/tools?”](https://docs.papermc.io/adventure/faq/#why-am-i-getting-a-nosuchfielderror-nosuchmethoderror-classnotfoundexception-or-similar-when-updatingusing-adventure-platform--adventure-text-minimessage-adventure-api-or-other-related-librariestools) In the case of `adventure-platform-fabric`, you need to make sure you are properly `include()`\-`ing` the mod. For legacy platform implementations, you need to make sure you are properly shading and relocating your specific dependencies. Specific issues may include: * Not shading the correct version of `adventure-api`. You can check your dependency tree to see what or why your build tool is not including the correct version of the API that matches the one used by the platform version you are using. * Not relocating your dependencies. If you are running on a platform that includes an older version of the API, or another mod/plugin is also not properly relocating their dependencies, you will use their out-of-date version of the API, causing errors. * Building/running against a native implementation of `adventure-api`. If you are running on a platform that includes an older version of the API, this could cause issues if the library depends on newer features that are not available in the outdated version of the API, your library will not be able to find these methods, causing errors. * Relocating `adventure-api` and trying to use native/library methods. If you relocate the API, you will not be able to use any methods that use the API in native implementations or libraries as method signatures will differ. Either shade and relocate this software, or do not use native methods. Alternatively, if you are shading and relocating a library but want to use the API, make sure you are only relocating the packages that you are shading. Please consult the documentation for your build tool for more information on how to shade, relocate and manage your dependencies. We do not provide one-on-one support for these sorts of issues, as there are far too many project-specific variables that make isolating issues difficult. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Frequently asked questions | PaperMC Docs [Skip to content](https://docs.papermc.io/folia/faq/#_top) Frequently asked questions ========================== What server types can benefit from Folia? ----------------------------------------- [Section titled “What server types can benefit from Folia?”](https://docs.papermc.io/folia/faq/#what-server-types-can-benefit-from-folia) Server types that naturally spread players out, like skyblock or SMP, will benefit the most from Folia. The server should have a sizeable player count, too. What hardware will Folia run best on? ------------------------------------- [Section titled “What hardware will Folia run best on?”](https://docs.papermc.io/folia/faq/#what-hardware-will-folia-run-best-on) Ideally, at least 16 _cores_ (not threads). How to best configure Folia? ---------------------------- [Section titled “How to best configure Folia?”](https://docs.papermc.io/folia/faq/#how-to-best-configure-folia) First, it is recommended that the world is pre-generated so that the number of chunk system worker threads required is reduced greatly. The following is a _very rough_ estimation based off of the testing done before Folia was released on the test server we ran that had ~330 players peak. So, it is not exact and will require further tuning - just take it as a starting point. The total number of cores on the machine available should be taken into account. Then, allocate threads for: * netty IO: ~4 per 200-300 players * chunk system io threads: ~3 per 200-300 players * chunk system workers if pre-generated, ~2 per 200-300 players * There is no best guess for chunk system workers if not pre-generated, as on the test server we ran we gave 16 threads but chunk generation was still slow at ~300 players. * GC Settings: ???? But, GC settings _do_ allocate concurrent threads, and you need to know exactly how many. This is typically through the `-XX:ConcGCThreads=n` flag. Do not confuse this flag with `-XX:ParallelGCThreads=n`, as parallel GC threads only run when the application is paused by GC and as such should not be taken into account. After all of that allocation, the remaining cores on the system until 80% allocation (total threads allocated < 80% of cpus available) can be allocated to tickthreads (under global config, `threaded-regions.threads`). The reason you should not allocate more than 80% of the cores is due to the fact that plugins or even the server may make use of additional threads that you cannot configure or even predict. Additionally, the above is all a rough guess based on player count, but it is very likely that the thread allocation will not be ideal, and you will need to tune it based on usage of the threads that you end up seeing. What commands does Folia disable? --------------------------------- [Section titled “What commands does Folia disable?”](https://docs.papermc.io/folia/faq/#what-commands-does-folia-disable) Folia currently disables a handful of commands. These are them: * Bossbar commands * Clone commands * Data commands * Datapack * Debug * Function * Item commands * Loot * Reload * Return * Ride * Rotate * Schedule * Scoreboard * Spectate * SpreadPlayers * Tag * Team * TeamMsg * Tick * Trigger * Perf * SaveAll * Restart Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Administration | PaperMC Docs [Skip to content](https://docs.papermc.io/folia/admin/#_top) Administration ============== Welcome to the Folia administration guide! This guide includes information and tutorials regarding the administration of a Folia server. #### Reference [Section titled “Reference”](https://docs.papermc.io/folia/admin/#reference) [Overview](https://docs.papermc.io/folia/reference/overview) An overview of how Folia works. [Region logic](https://docs.papermc.io/folia/reference/region-logic) An overview to how Folia's regionizer works. [Frequently asked questions](https://docs.papermc.io/folia/faq) Questions frequently asked by our community, answered by us! Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Reference | PaperMC Docs [Skip to content](https://docs.papermc.io/folia/admin/reference/#_top) Reference ========= A reference of how Folia works. [Overview](https://docs.papermc.io/folia/reference/overview) An overview of how Folia works. [Region logic](https://docs.papermc.io/folia/reference/region-logic) An overview to how Folia's regionizer works. [Frequently asked questions](https://docs.papermc.io/folia/faq) Questions frequently asked by our community, answered by us! Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Region logic | PaperMC Docs [Skip to content](https://docs.papermc.io/folia/reference/region-logic/#_top) Region logic ============ Fundamental regionizing logic ----------------------------- [Section titled “Fundamental regionizing logic”](https://docs.papermc.io/folia/reference/region-logic/#fundamental-regionizing-logic) Region ------ [Section titled “Region”](https://docs.papermc.io/folia/reference/region-logic/#region) A region is simply a set of owned chunk positions and implementation defined unique data object tied to that region. It is important to note that for any non-dead region x, that for each chunk position y it owns that there is no other non-dead region z such that the region z owns the chunk position y. Regionizer ---------- [Section titled “Regionizer”](https://docs.papermc.io/folia/reference/region-logic/#regionizer) Each world has its own regionizer. The regionizer is a term used to describe the logic that the class `ThreadedRegionizer` executes to create, maintain, and destroy regions. Maintenance of regions is done by merging nearby regions together, marking which regions are eligible to be ticked, and finally by splitting any regions into smaller independent regions. Effectively, it is the logic performed to ensure that groups of nearby chunks are considered a single independent region. Guarantees the regionizer provides ---------------------------------- [Section titled “Guarantees the regionizer provides”](https://docs.papermc.io/folia/reference/region-logic/#guarantees-the-regionizer-provides) The regionizer provides a set of important invariants that allows regions to tick in parallel without race conditions: ### First invariant [Section titled “First invariant”](https://docs.papermc.io/folia/reference/region-logic/#first-invariant) The first invariant is simply that any chunk holder that exists has one, and only one, corresponding region. ### Second invariant [Section titled “Second invariant”](https://docs.papermc.io/folia/reference/region-logic/#second-invariant) The second invariant is that for every _existing_ chunk holder x that is contained in a region that every each chunk position within the “merge radius” of x is owned by the region. Effectively, this invariant guarantees that the region is not close to another region, which allows the region to assume while ticking it can create data for chunk holders “close” to it. ### Third invariant [Section titled “Third invariant”](https://docs.papermc.io/folia/reference/region-logic/#third-invariant) The third invariant is that a ticking region _cannot_ expand the chunk positions it owns as it ticks. The third invariant is important as it prevents ticking regions from “fighting” over non-owned nearby chunks, to ensure that they truly tick in parallel, no matter what chunk loads they may issue while ticking. To comply with the first invariant, the regionizer will create “transient” regions _around_ ticking regions. Specifically, around in this context means close enough that would require a merge, but not far enough to be considered independent. The transient regions created in these cases will be merged into the ticking region when the ticking region finishes ticking. Both of the second invariant and third invariant combined allow the regionizer to guarantee that a ticking region may create and then access chunk holders around it (i.e. sync loading) without the possibility that it steps on another region’s toes. ### Fourth invariant [Section titled “Fourth invariant”](https://docs.papermc.io/folia/reference/region-logic/#fourth-invariant) The fourth invariant is that a region is only in one of four states: “transient”, “ready”, “ticking”, or “dead.” The “ready” state allows a state to transition to the “ticking” state, while the “transient” state is used as a state for a region that may not tick. The “dead” state is used to mark regions which should not be use. The states transitions are explained later, as it ties in with the regionizer’s merge and split logic. Regionizer implementation ------------------------- [Section titled “Regionizer implementation”](https://docs.papermc.io/folia/reference/region-logic/#regionizer-implementation) The regionizer implementation is a description of how the class `ThreadedRegionizer` adheres to the four invariants described previously. ### Splitting the world into sections [Section titled “Splitting the world into sections”](https://docs.papermc.io/folia/reference/region-logic/#splitting-the-world-into-sections) The regionizer does not operate on chunk coordinates, but rather on “region section coordinates.” Region section coordinates simply represent a grouping of NxN chunks on a grid, where N is some power of two. The actual number is left ambiguous, as region section coordinates are only an internal detail of how chunks are grouped. For example, with N=16 the region section (0,0) encompasses all chunks x in \[0,15\] and z in \[0,15\]. This concept is similar to how the chunk coordinate (0,0) encompasses all blocks x in \[0, 15\] and z in \[0, 15\]. Another example with N=16, the chunk (17, -5) is contained within region section (1, -1). Region section coordinates are used only as a performance tradeoff in the regionizer, as by approximating chunks to their region coordinate allows it to treat NxN chunks as a single unit for regionizing. This means that regions do not own chunks positions, but rather own region section positions. The grouping of NxN chunks allows the regionizing logic to be performed only on the creation/destruction of region sections. For example with N=16 this means up to NxN-1=255 possible less operations in areas such as addChunk/region recalculation assuming region sections are always full. ### Implementation variables [Section titled “Implementation variables”](https://docs.papermc.io/folia/reference/region-logic/#implementation-variables) The implementation variables control how aggressively the regionizer will maintain regions and merge regions. #### Recalculation count [Section titled “Recalculation count”](https://docs.papermc.io/folia/reference/region-logic/#recalculation-count) The recalculation count is the minimum number of region sections that a region must own to allow it to re-calculate. Note that a recalculation operation simply calculates the set of independent regions that exist within a region to check if a split can be performed. This is a simple performance knob that allows split logic to be turned off for small regions, as it is unlikely that small regions can be split in the first place. #### Max dead section percent [Section titled “Max dead section percent”](https://docs.papermc.io/folia/reference/region-logic/#max-dead-section-percent) The max dead section percent is the minimum percent of dead sections in a region that must exist before a region can run re-calculation logic. #### Empty section creation radius [Section titled “Empty section creation radius”](https://docs.papermc.io/folia/reference/region-logic/#empty-section-creation-radius) The empty section creation radius variable is used to determine how many empty region sections are to exist around _any_ region section with at least one chunk. Internally, the regionizer enforces the third invariant by preventing ticking regions from owning new region sections. The creation of empty sections around any non-empty section will then enforce the second invariant. #### Region section merge radius [Section titled “Region section merge radius”](https://docs.papermc.io/folia/reference/region-logic/#region-section-merge-radius) The merge radius variable is used to ensure that for any existing region section x that for any other region section y within the merge radius are either owned by region that owns x or are pending a merge into the region that owns x or that the region that owns x is pending a merge into the region that owns y. #### Region section chunk shift [Section titled “Region section chunk shift”](https://docs.papermc.io/folia/reference/region-logic/#region-section-chunk-shift) The region section chunk shift is simply log2(grid size N). Thus, N = 1 << region section chunk shift. The conversion from chunk position to region section is additionally defined as region coordinate = chunk coordinate >> region section chunk shift. ### Operation [Section titled “Operation”](https://docs.papermc.io/folia/reference/region-logic/#operation) The regionizer is operated by invoking `ThreadedRegionizer#addChunk(x, z)` or `ThreadedRegionizer#removeChunk(x, z)` when a chunk holder is created or destroyed. Additionally, `ThreadedRegion#tryMarkTicking` can be used by a caller that attempts to move a region from the “ready” state to the “ticking” state. It is vital to note that this function will return false if the region is not in the “ready” state, as it is possible that even a region considered to be “ready” in the past (i.e. scheduled to tick) may be unexpectedly marked as “transient.” Thus, the caller needs to handle such cases. The caller that successfully marks a region as ticking must mark it as non-ticking by using `ThreadedRegion#markNotTicking`. The function ThreadedRegion#markNotTicking returns true if the region was migrated from “ticking” state to “ready” state, and false in all other cases. Effectively, it returns whether the current region may be later ticked again. ### Region section state [Section titled “Region section state”](https://docs.papermc.io/folia/reference/region-logic/#region-section-state) A region section state is one of “dead” or “alive.” A region section may additionally be considered “non-empty” if it contains at least one chunk position, and “empty” otherwise. A region section is considered “dead” if and only if the region section is also “empty” and that there exist no other “empty” sections within the empty section creation radius. The existence of the dead section state is purely for performance, as it allows the recalculation logic of a region to be delayed until the region contains enough dead sections. However, dead sections are still considered to belong to the region that owns them just as alive sections. ### Addition of chunks (`addChunk`) [Section titled “Addition of chunks (addChunk)”](https://docs.papermc.io/folia/reference/region-logic/#addition-of-chunks-addchunk) The addition of chunks to the regionizer boils down to two cases: #### Target region section already exists and is not empty [Section titled “Target region section already exists and is not empty”](https://docs.papermc.io/folia/reference/region-logic/#target-region-section-already-exists-and-is-not-empty) In this case, it simply adds the chunk to the section and returns. #### Target region section does not exist or is empty [Section titled “Target region section does not exist or is empty”](https://docs.papermc.io/folia/reference/region-logic/#target-region-section-does-not-exist-or-is-empty) In this case, the region section will be created if it does not exist. Additionally, the region sections in the “create empty radius” will be created as well. Then, any region in the create empty radius + merge radius are collected into a set X. This set represents the regions that need to be merged later to adhere to the second invariant. If the set X contains no elements, then a region is created in the ready state to own all of the created sections. If the set X contains just 1 region, then no regions need to be merged and no region state is modified, and the sections are added to this 1 region. Merge logic needs to occur when there are more than 1 region in the set X. From the set X, a region x is selected that is not ticking. If no such x exists, then a region x is created. Every region section created is added to the set x, as it is the section that is known to not be ticking - this is done to adhere to the third invariant. Every region y in the set X that is not x is merged into x if y is not in the ticking state, otherwise x runs the merge later logic into y. ### Merge later logic [Section titled “Merge later logic”](https://docs.papermc.io/folia/reference/region-logic/#merge-later-logic) A merge later operation may only take place from a non-ticking, non-dead region x into a ticking region y. The merge later logic relies on maintaining a set of regions to merge into later per region, and another set of regions that are expected to merge into this region. Effectively, a merge into later operation from x into y will add y into x’s merge into later set, and add x into y’s expecting merge from set. When the ticking region finishes ticking, the ticking region will perform the merge logic for all expecting merges. ### Merge logic [Section titled “Merge logic”](https://docs.papermc.io/folia/reference/region-logic/#merge-logic) A merge operation may only take place between a dead region x and another region y which may be either “transient” or “ready.” The region x is effectively absorbed into the region y, as the sections in x are moved to the region y. The merge into later is also forwarded to the region y, such so that the regions x was to merge into later, y will now merge into later. Additionally, if there is implementation specific data on region x, the region callback to merge the data into the region y is invoked. The state of the region y may be updated after a merge operation completes. For example, if the region x was “transient”, then the region y should be downgraded to transient as well. Specifically, the region y should be marked as transient if region x contained merge later targets that were not y. The downgrading to transient is required to adhere to the second invariant. ### Removal of chunks (`removeChunk`) [Section titled “Removal of chunks (removeChunk)”](https://docs.papermc.io/folia/reference/region-logic/#removal-of-chunks-removechunk) Removal of chunks from region sections simple updates the region sections state to “dead” or “alive”, as well as the region sections in the empty creation radius. It will not update any region state, and nor will it purge region sections. ### Region tick start (`tryMarkTicking`) [Section titled “Region tick start (tryMarkTicking)”](https://docs.papermc.io/folia/reference/region-logic/#region-tick-start-trymarkticking) The tick start simply migrates the state to ticking, so that invariants #2 and #3 can be met. ### Region tick end (`markNotTicking`) [Section titled “Region tick end (markNotTicking)”](https://docs.papermc.io/folia/reference/region-logic/#region-tick-end-marknotticking) At the end of a tick, the region’s new state is not immediately known. First, the region must process its pending merges. After it processes its pending merges, it must then check if the region is now pending merge into any other region. If it is, then it transitions to the transient state. Otherwise, it will process the removal of dead sections and attempt to split into smaller regions. Note that it is guaranteed that if a region can be possibly split, it must remove dead sections, otherwise, this would contradict the rules used to build the region in the first place. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Overview | PaperMC Docs [Skip to content](https://docs.papermc.io/folia/reference/overview/#_top) Overview ======== Described in this document is the abstract overview of changes done by Folia. Folia splits the chunks within all loaded worlds into independently ticking regions so that the regions are ticked independently and in parallel. Described first will be intra region operations, and then inter region operations. Rules for independent regions ----------------------------- [Section titled “Rules for independent regions”](https://docs.papermc.io/folia/reference/overview/#rules-for-independent-regions) In order to ensure that regions are independent, the rules for maintaining regions must ensure that a ticking region has no directly adjacent neighbor regions which are ticking. The following rules guarantee the invariant is upheld: 1. Any ticking region may not grow while it is ticking. 2. Any ticking region must initially own a small buffer of chunks outside its perimeter. 3. Regions may not _begin_ to tick if they have a neighboring adjacent region. 4. Adjacent regions must eventually merge to form a single region. Additionally, to ensure that a region is not composed of independent regions (which would hinder parallelism), regions composed of more than one independent area must be eventually split into independent regions when possible. Finally, to ensure that ticking regions may store and maintain data about the current region (i.e. tick count, entities within the region, chunks within the region, block/fluid tick lists, and more), regions have their own data object that may only be accessed while ticking the region and by the thread ticking the region. Also, there are callbacks to merging or splitting regions so that the data object may be updated appropriately. The implementation of these rules is described in [Region Logic](https://docs.papermc.io/folia/reference/region-logic) . The end result of applying these rules is that a ticking region can ensure that only the current thread has write access to any data contained within the region, and that at any given time the number of independent regions is close to maximum. Intra-region operations ----------------------- [Section titled “Intra-region operations”](https://docs.papermc.io/folia/reference/overview/#intra-region-operations) Intra-region operations refer to any operations that only deal with data for a single region by the owning region, or to merge/split logic. ### Ticking for independent regions [Section titled “Ticking for independent regions”](https://docs.papermc.io/folia/reference/overview/#ticking-for-independent-regions) Independent regions tick independently and in parallel. To tick independently means that regions maintain their own deadlines for scheduling the next tick. For example, consider two regions A and B such that A’s next tick start is at t=15ms and B’s next tick start is at t=0ms. Consider the following sequence of events: 1. At t = 0ms, B begins to tick. 2. At t = 15ms, A begins to tick. 3. At t = 20ms, B is finished its tick. It is then scheduled to tick again at t = 50ms. 4. At t = 50ms, B begins its 2nd tick. 5. At t = 70ms, B finishes its 2nd tick and is scheduled to tick again at t = 100ms. 6. At t = 95ms, A finishes its _first_ tick. It is scheduled to tick again at t = 95ms. It is important to note that at no time was B’s schedule affected by the fact that A fell behind its 20TPS target. To implement the described behavior, each region maintains a repeating task on a scheduled executor (see `SchedulerThreadPool`) that schedules tasks according to an earliest-start-time-first scheduling algorithm. The algorithm is similar to EDF, but schedules according to start time. However, given that the deadline for each tick is 50ms + the start time, it behaves identically to the EDF algorithm. The EDF-like algorithm is selected so that as long as the thread pool is not maximally utilized, that all regions that take <= 50ms to tick will maintain 20TPS. However, the scheduling algorithm is neither NUMA aware nor CPU core aware - it will not make attempts (when n regions > m threads) to pin regions to certain cores. Since regions tick independently, they maintain their own tick counters. The implications of this are described in the next section. ### Tick counters [Section titled “Tick counters”](https://docs.papermc.io/folia/reference/overview/#tick-counters) In standard Vanilla, there are several important tick counters: Current Tick, Game Time Tick, and Daylight Time Tick. The Current Tick counter is used for determining the tick number since the server has booted. The Game Time Tick is maintained per world and is used to schedule block ticks for redstone, fluids, and other physics events. The Daylight Time Tick is simply the number of ticks since noon, maintained per world. In Folia, the Current Tick is maintained per region. The Game Time Tick is split into two counters: Redstone Time and Global Game Time. Redstone Time is maintained per region. Global Game Time and Daylight Time are maintained by the “global region.” At the start of each region tick, the global game time tick and daylight time tick are copied from the global region and any time the current region retrieves those values, it will retrieve from the copy received at the start of tick. This is to ensure that for any two calls to retrieve the tick number throughout the tick, that those two calls report the same tick number. The global game time is maintained for a couple of reasons: 1. There needs to be a counter representing how many ticks a world has existed for, since the game does track total number of days the world has gone on for. 2. Significant amounts of new entity AI code uses game time (for a reason I cannot divine) to store absolute deadlines of tasks. It is not impossible to write code to adjust the deadlines of all of these tasks, but the amount of work is significant. #### Global region [Section titled “Global region”](https://docs.papermc.io/folia/reference/overview/#global-region) The global region is a single scheduled task that is always scheduled to run at 20TPS that is responsible for maintaining data that is not tied to any specific region: game rules, global game time, daylight time, console command handling, world border, weather, and others. Unlike the other regions, the global region does not need to perform any special logic for merging or splitting because it is never split or merged - there is only one global region at any time. The global region does not own any region specific data. #### Merging and splitting region tick times [Section titled “Merging and splitting region tick times”](https://docs.papermc.io/folia/reference/overview/#merging-and-splitting-region-tick-times) Since redstone and current ticks are maintained per region, there needs to be appropriate logic to adjust the tick deadlines used by the block/fluid tick scheduler and anything else that schedules by redstone/current absolute tick time so that the relative deadline is unaffected. When merging a region x (from) into a region y (into or to), we can either adjust both the deadlines of x and y or just one of x and y. It is simply easier to adjust one, and arbitrarily the region x is chosen. Then, the deadlines of x must be adjusted so that considering the current ticks of y that the relative deadlines remain unchanged. Consider a deadline d1 = from tick + relative deadline in region x. We then want the adjusted deadline d2 to be d2 = to tick + relative deadline in region y, so that the relative tick deadline is maintained. We can achieve this by applying an offset o to d1 so that d1 + o = d2, and the offset used is o = tick to - tick from. This offset must be calculated for redstone tick and current tick separately, since the logic to increase redstone tick can be turned off by the `Level#tickTime` field. Finally, the split case is easy - when a split occurs, the independent regions from the split inherit the redstone/current tick from the parent region. Thus, the relative deadlines are maintained as there is no tick number change. In all cases, redstone or any other events scheduled by current tick remain unaffected when regions split or merge as the relative deadline is maintained by applying an offset in the merge case and by copying the tick number in the split case. Inter-region operations ----------------------- [Section titled “Inter-region operations”](https://docs.papermc.io/folia/reference/overview/#inter-region-operations) Inter-region operations refer to operations that work with other regions that are not the current ticking region that are in a completely unknown state. These regions may be transient, may be ticking, or may not even exist. ### Utilities to assist operations [Section titled “Utilities to assist operations”](https://docs.papermc.io/folia/reference/overview/#utilities-to-assist-operations) In order to assist in inter region operations, several utilities are provided. In NMS, these utilities are the `EntityScheduler`, the `RegionizedTaskQueue`, the global region task queue, and the region-local data provider `RegionizedData`. The Folia API has similar analogues, but does not have a region-local data provider as the NMS data provider holds critical locks and is invoked in critical areas of code when performing any callback logic and is thus highly susceptible to fatal plugin errors involving lengthy I/O or world state modification. #### `EntityScheduler` [Section titled “EntityScheduler”](https://docs.papermc.io/folia/reference/overview/#entityscheduler) The `EntityScheduler` allows tasks to be scheduled to be executed on the region that owns the entity. This is particularly useful when dealing with entity teleportation, as once an entity begins an asynchronous teleport the entity cannot tick until the teleport has completed, and the timing is undefined. #### `RegionizedTaskQueue` [Section titled “RegionizedTaskQueue”](https://docs.papermc.io/folia/reference/overview/#regionizedtaskqueue) The `RegionizedTaskQueue` allows tasks to be scheduled to be executed on the next tick of a region that owns a specific location, or creating such region if it does not exist. This is useful for tasks that may need to edit or retrieve world/block/chunk data outside the current region. #### Global region task queue [Section titled “Global region task queue”](https://docs.papermc.io/folia/reference/overview/#global-region-task-queue) The global region task queue is simply used to perform edits on data that the global region owns, such as game rules, day time, weather, or to execute commands using the console command sender. #### `RegionizedData` [Section titled “RegionizedData”](https://docs.papermc.io/folia/reference/overview/#regionizeddata) The `RegionizedData` class allows regions to define region-local data, which allow regions to store data without having to consider concurrent data access from other regions. For example, current per region entity/chunk/block/fluid tick lists are maintained so that regions do not need to consider concurrent access to these data sets. The utilities allow various cross-region issues to be resolved in a simple fashion, such as editing block/entity/world state from any region by using tasks queues, or by avoiding concurrency issues by using RegionizedData. More advanced operations such as teleportation, player respawning, and portalling, all make use of these utilities to ensure the operation is thread-safe. ### Entity intra- and inter-dimension teleports [Section titled “Entity intra- and inter-dimension teleports”](https://docs.papermc.io/folia/reference/overview/#entity-intra--and-inter-dimension-teleports) Entities need special logic in order to teleport safely between other regions or other dimensions. In all cases however, the call to teleport/place an entity must be invoked on the region owning the entity. The `EntityScheduler` can be used to easily schedule code to execute in such a context. #### Simple teleportation [Section titled “Simple teleportation”](https://docs.papermc.io/folia/reference/overview/#simple-teleportation) In a simple teleportation, the entity already exists in a world at a location and the target location and dimension are known. This operation is split into two parts: transform and async place. In this case, the transform operation removes the entity from the current world, then adjusts the position. The async place operation schedules a task to the target location using the `RegionizedTaskQueue` to add the entity to the target dimension at the target position. The various implementation details such as non-player entities being copied in the transform operation are left out, as those are not relevant for the high level overview. Things such as player login and player respawn are generally considered simple teleportation. The player login case only differs since the player does not exist in any world at the start, and that the async transform must additionally find a place to spawn the player. The player respawn is similar to the player login as the respawn differs by having the player in the world at the time of respawn. #### Portal teleport [Section titled “Portal teleport”](https://docs.papermc.io/folia/reference/overview/#portal-teleport) Portal teleport differs from simple teleportation as portalling does _not_ know the exact location of the teleport. Thus, the transform step does not update the entity position, but rather a new operation is inserted between transform and async place: an async search/create, which is responsible for finding and/or creating the exit portal. Additionally, the current Vanilla code can refuse a teleport if the entity is non-player and the nether exit portal does not already exist. But since the portal location is only determined by the async place, it is too late to abort - so, the portal logic has been re-done so that there is no difference between players and entities. Now both entities and players create exit portals, whether it be for the nether or end. #### Shutdown during teleport [Section titled “Shutdown during teleport”](https://docs.papermc.io/folia/reference/overview/#shutdown-during-teleport) Since the teleport happens over multiple steps, the server shutdown process must deal with uncompleted teleportations manually. Server shutdown process ----------------------- [Section titled “Server shutdown process”](https://docs.papermc.io/folia/reference/overview/#server-shutdown-process) The shutdown process occurs by spawning a separate shutdown thread, which then runs the shutdown logic: 1. Shutdown the tick region scheduler, stopping any further ticks 2. Halt metrics processing 3. Disable plugins 4. Stop accepting new connections 5. Send disconnect (but do not remove) packets to all players 6. Halt the chunk systems for all worlds 7. Execute shutdown logic for all worlds by finish all pending teleports for all regions, then saving all chunks in the world, and finally saving the level data for the world (level.dat and other .dat files). 8. Save all players 9. Shutting down the resource manager 10. Releasing the level lock 11. Halting remaining executors (Util executor, region I/O threads, etc.) The important differences to Vanilla is that the player kick and world saving logic is replaced by steps 5-8. For step 5, the players cannot be kicked before teleportations are finished, as kicking would save the player dat file. So, save is moved after. For step 6, the chunk system halt is done before saving so that all chunk generation is halted. This will reduce the load on the server as it shuts down, which may be critical in memory-constrained scenarios. For step 7, teleportations are completed differently depending on the type: simple or portal. Simple teleportations are completed by ensuring the addition of the teleporting entity to the destination chunk specified by teleportation. This allows the entity to be saved at the target position, as if the teleportation did complete before shutdown. Portal teleportations are completed by forcing the addition of the teleporting entity to the source chunk, from where the entity should have been teleported _from_. Since the target location is not known, the entity can only be placed back at the origin (no teleportation). While this behavior is not ideal, the shutdown logic _must_ account for any broken world state - which means that finding or creating the target exit portal may not be an option. The teleportation completion must be performed before the world save so that the teleport completed entities save. For step 8, only save players after the teleportations are completed. The remaining steps are Vanilla. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Contact us | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/contact/#_top) Contact us ========== Discord ------- [Section titled “Discord”](https://docs.papermc.io/misc/contact/#discord) The PaperMC project handles most communication via Discord. Use the following invite: [https://discord.gg/papermc](https://discord.gg/papermc) Forums ------ [Section titled “Forums”](https://docs.papermc.io/misc/contact/#forums) Reach out for support, or contact us on our forums. * [Forums](https://forums.papermc.io/) Twitter/X --------- [Section titled “Twitter/X”](https://docs.papermc.io/misc/contact/#twitterx) We often tweet out version release notes, update notices, and other information via our Twitter page. * [@PaperPowered](https://x.com/PaperPowered) You should not DM or @ this account for support. It is not checked as regularly as the above locations. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Art assets | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/assets/#_top) Art assets ========== This page provides the official PaperMC and Velocity logomarks and the terms under which you may use them. Images on this page are available through our CDN, and using the provided URLs is encouraged (but not necessary) when referencing these assets in your projects, as long as you adhere to the usage guidelines outlined below. PaperMC ------- [Section titled “PaperMC”](https://docs.papermc.io/misc/assets/#papermc) You may: * Use the PaperMC logomark to represent the project in blogposts and other places in order to bring attention to the project. * Use the PaperMC logomark to represent Paper-Server in downloads, server selectors, and similar places. * Crop out extra transparent canvas space behind the PaperMC logomark, so it fits better next to other content. You may not: * Alter any of the colors used in the PaperMC logomark. * Change the dimensions of the PaperMC logomark. * Create modified versions of the PaperMC logomark or derivative works of it. * Add your own project images or branding to the PaperMC logomark. * Claim the logomark as your own work or use it as a representation of your own projects. * Sell the PaperMC logomark on its own or as part of other products without explicit permission. * Alter the transparency of any elements within the PaperMC logomark. | Image | URL | | --- | --- | | ![](https://docs.papermc.io/_astro/papermc_combination_mark_dark.min_1G4IA.svg) | `https://assets.papermc.io/brand/papermc_combination_mark_dark.min.svg` | | ![](https://docs.papermc.io/_astro/papermc_combination_mark_light.min_AbM0.svg) | `https://assets.papermc.io/brand/papermc_combination_mark_light.min.svg` | | ![](https://docs.papermc.io/_astro/papermc_logo.min_ZQWpHc.svg) | `https://assets.papermc.io/brand/papermc_logo.min.svg` | | ![](https://docs.papermc.io/_astro/papermc_logo.256_Z2eA2bD.webp) | `https://assets.papermc.io/brand/papermc_logo.256.png` | | ![](https://docs.papermc.io/_astro/papermc_logo.512_Z1dsfe4.webp) | `https://assets.papermc.io/brand/papermc_logo.512.png` | Velocity -------- [Section titled “Velocity”](https://docs.papermc.io/misc/assets/#velocity) Please do not edit, recolor, rearrange, or distort the Velocity logo. Resizing the logo and cropping out any blank space is acceptable. The logo should not be used in a matter that suggests the Velocity project officially endorses some product or service. For instance, you may advertise a plugin as being compatible with Velocity, but you may not make the Velocity logo prominent in that advertising. | Image | URL | | --- | --- | | ![](https://docs.papermc.io/_astro/velocity_combination_mark_blue.min_15aerd.svg) | `https://assets.papermc.io/brand/velocity_combination_mark_blue.min.svg` | | ![](https://docs.papermc.io/_astro/velocity_combination_mark_white.min_Z5TdHX.svg) | `https://assets.papermc.io/brand/velocity_combination_mark_white.min.svg` | | ![](https://docs.papermc.io/_astro/velocity_logo_blue.min_Z1MNEnN.svg) | `https://assets.papermc.io/brand/velocity_logo_blue.min.svg` | | ![](https://docs.papermc.io/_astro/velocity_logo_white.min_XnOwp.svg) | `https://assets.papermc.io/brand/velocity_logo_white.min.svg` | Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Diff viewer | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/tools/diff-viewer/#_top) Diff viewer =========== Multi-file rich diff viewer with support for GitHub commits, PRs, and comparisons, as well as diff and patch files. The GitHub diff viewer is a great tool for most use cases, but it has a variety of limitations, especially when dealing with large diffs where the viewer will perform poorly or even crash. The diffs.dev Diff Viewer aims to solve this problem while also providing a variety of additional features useful for PaperMC and generally, such as special handling for second-order diffs. We have also built a browser extension for Firefox and Chrome to streamline opening GitHub diffs in the viewer. * [https://diffs.dev](https://diffs.dev/) - The diff viewer itself * [Chrome Extension](https://chromewebstore.google.com/detail/patch-roulette/feaaoepdocmiibjilhoahgldkaajfnhb) * [Firefox Add-on](https://addons.mozilla.org/en-US/firefox/addon/patch-roulette/) * [https://github.com/PaperMC/diff-viewer](https://github.com/PaperMC/diff-viewer) - GitHub repository Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # MiniMessage web editor | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/tools/minimessage-web-editor/#_top) MiniMessage web editor ====================== The MiniMessage Web Editor is a web-based editor for creating and previewing MiniMessage-formatted text. It is hosted here: [MiniMessage Web Editor](https://webui.advntr.dev/) . ![Image of adventure webui](https://docs.papermc.io/_astro/adventure-webui.D0wW6e1b_Z1AHbcb.webp) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Item command converter | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/tools/item-command-converter/#_top) Item command converter ====================== In 1.20.5, Mojang has moved from unstructured NBT to the so-called item components. While Minecraft will automatically update all existing items for you, only Paper will update commands and text components containing items where possible. This tool helps you convert old item commands to the new format externally. Note that you need to select the _Entity Argument_ mode if you want to convert entity data outside of the summon command, as we require the entity type to convert data correctly. Input: Convert Mode: CommandItem argumentComponent argumentEntity argument Output: Copy Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Getting started | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/getting-started/#_top) Getting started =============== To use Adventure in your project, you will need to add the following dependency (and repository if using Gradle): Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/getting-started/#tab-panel-3) * [Gradle (Groovy)](https://docs.papermc.io/adventure/getting-started/#tab-panel-4) * [Maven](https://docs.papermc.io/adventure/getting-started/#tab-panel-5) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-api:5.2.0")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-api:5.2.0'} net.kyori adventure-api 5.2.0 Need development/snapshot builds? [Using Snapshot Builds](https://docs.papermc.io/adventure/getting-started/#using-snapshot-builds) Some platforms already use Adventure natively. In this case, you will not need to add Adventure as a dependency. To view the list of platforms that include Adventure, see [Native Support](https://docs.papermc.io/adventure/platform/native) . To use Adventure with other platforms, you may wish to look at the platform-specific adapters. A list of platforms with supported adapters can be found at [Platforms](https://docs.papermc.io/adventure/platform) . Using snapshot builds --------------------- [Section titled “Using snapshot builds”](https://docs.papermc.io/adventure/getting-started/#using-snapshot-builds) To use snapshot builds, you will need to add the following repository: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/getting-started/#tab-panel-0) * [Gradle (Groovy)](https://docs.papermc.io/adventure/getting-started/#tab-panel-1) * [Maven](https://docs.papermc.io/adventure/getting-started/#tab-panel-2) repositories { maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { name = "central-snapshots" }} repositories { maven { name = 'central-snapshots' url = 'https://central.sonatype.com/repository/maven-snapshots/' }} central-snapshots https://central.sonatype.com/repository/maven-snapshots/ Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Tools | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/tools/#_top) Tools ===== Collection of useful tools for server admins or plugin developers. [Start script generator](https://docs.papermc.io/misc/tools/start-script-gen) A start script generator for PaperMC projects. [Item command converter](https://docs.papermc.io/misc/tools/item-command-converter) A tool to update commands from the old NBT-based item format to item components. [MiniMessage web editor](https://docs.papermc.io/misc/tools/minimessage-web-editor) A web-based editor for creating and previewing MiniMessage-formatted text. [Diff viewer](https://docs.papermc.io/misc/tools/diff-viewer) Multi-file rich diff viewer for GitHub and diff/patch files. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Start script generator | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/tools/start-script-gen/#_top) Start script generator ====================== What flags do I choose? If you’re running on a modern JVM, i.e. 17, 21 or higher, try with no flags first. Modern JVMs are very good at handling various applications with default GC settings. If you have GC problems or are running an older version of Minecraft/an older version of Java, try [Aikar’s flags](https://docs.papermc.io/paper/aikars-flags) , which are optimized specifically for Minecraft. If you’re generating a script for starting [Velocity](https://papermc.io/software/velocity) , choose “Velocity”. Memory: 4GB 4GB8GB12GB16GB20GB File name: Platform: Linux/MacWindows Flags: NoneAikar'sVelocity GUI Auto-restart #!/usr/bin/env sh java -Xms4096M -Xmx4096M -jar server.jar --nogui Copy Download Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Miscellaneous | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/#_top) Miscellaneous ============= Documentation that does not cleanly fit in any other category. [Art assets](https://docs.papermc.io/misc/assets) The official PaperMC and Velocity logomarks and the terms under which you may use them. [Contact us](https://docs.papermc.io/misc/contact) There are many ways to contact us, see here for more information. [Downloads Service](https://docs.papermc.io/misc/downloads-service) Paper provides a downloads service that you can use to access builds. [Hangar auto-publishing](https://docs.papermc.io/misc/hangar-publishing) How to automatically publish your plugin to Hangar on commits. [Installing or updating Java](https://docs.papermc.io/misc/java-install) How to install or update to Java 25 on Linux (apt/rpm), Windows, or Mac. [🗃️ Tools](https://docs.papermc.io/misc/tools) (documentation group) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Installing or updating Java | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/java-install/#_top) Installing or updating Java =========================== Installing Java is a critical first step to using or developing plugins for Paper and Velocity. This guide will walk you through the recommended installation steps for most major platforms. Linux ----- [Section titled “Linux”](https://docs.papermc.io/misc/java-install/#linux) ### Ubuntu/Debian [Section titled “Ubuntu/Debian”](https://docs.papermc.io/misc/java-install/#ubuntudebian) Installing Java 25 on Debian-based Linux distributions is very simple. First, ensure your system has all required tools to successfully install Java. sudo apt-get updatesudo apt-get install ca-certificates apt-transport-https gnupg wget Second, import the Amazon Corretto public key and apt repository. wget -O - https://apt.corretto.aws/corretto.key | sudo gpg --dearmor -o /usr/share/keyrings/corretto-keyring.gpg && \echo "deb [signed-by=/usr/share/keyrings/corretto-keyring.gpg] https://apt.corretto.aws stable main" | sudo tee /etc/apt/sources.list.d/corretto.list Then, install Java 25 and other dependencies using the following command: sudo apt-get updatesudo apt-get install -y java-25-amazon-corretto-jdk libxi6 libxtst6 libxrender1 Proceed to [verify your installation](https://docs.papermc.io/misc/java-install/#verifying-installation) . ### RPM-based [Section titled “RPM-based”](https://docs.papermc.io/misc/java-install/#rpm-based) To install Java 25 on CentOS, RHEL, Fedora, openSUSE, SLES, or any other RPM-based Linux distribution, execute the following commands depending on your package manager. Once you have finished, precede to [verify your installation](https://docs.papermc.io/misc/java-install/#verifying-installation) . #### DNF [Section titled “DNF”](https://docs.papermc.io/misc/java-install/#dnf) DNF is used on Fedora, CentOS/RHEL 7+, and related distributions. sudo rpm --import https://yum.corretto.aws/corretto.keysudo curl -Lo /etc/yum.repos.d/corretto.repo https://yum.corretto.aws/corretto.reposudo dnf -y install java-25-amazon-corretto-devel #### Zypper [Section titled “Zypper”](https://docs.papermc.io/misc/java-install/#zypper) Zypper is used on openSUSE, SLES, and related distributions. sudo zypper addrepo https://yum.corretto.aws/corretto.reposudo zypper refreshsudo zypper install java-25-amazon-corretto-devel #### YUM [Section titled “YUM”](https://docs.papermc.io/misc/java-install/#yum) YUM is used on older releases of CentOS/RHEL, and excessively old releases of Fedora. sudo rpm --import https://yum.corretto.aws/corretto.keysudo curl -Lo /etc/yum.repos.d/corretto.repo https://yum.corretto.aws/corretto.reposudo yum -y install java-25-amazon-corretto-devel Windows 10 & 11 --------------- [Section titled “Windows 10 & 11”](https://docs.papermc.io/misc/java-install/#windows-10--11) If you’re on Windows 10 or 11, installing Java is just like installing any other program. Download the Amazon Corretto installer from [their website](https://corretto.aws/downloads/latest/amazon-corretto-25-x64-windows-jdk.msi) . Once you have run the installer, it is safe to click “next” through the whole process. No additional bloatware or toolbars will be installed, and all the required features are enabled out of the box. Now, open a command prompt and precede to [verify your installation](https://docs.papermc.io/misc/java-install/#verifying-installation) . macOS/OS X ---------- [Section titled “macOS/OS X”](https://docs.papermc.io/misc/java-install/#macosos-x) If you’re on macOS, the best way to manage Java installations is with a tool called [Homebrew](https://brew.sh/) . Follow the instructions on their homepage to install it. Then, in your terminal run the following command: brew install openjdk@25 Once this command has completed, continue to [verify your installation](https://docs.papermc.io/misc/java-install/#verifying-installation) . Pterodactyl ----------- [Section titled “Pterodactyl”](https://docs.papermc.io/misc/java-install/#pterodactyl) If you have started a Paper server with an incorrect Java version, Pterodactyl will automatically prompt you to update like this: ![Pterodactyl Automatic Prompt](https://docs.papermc.io/_astro/pterodactyl-prompt.DsETHsod_ZxE5op.webp) If this does not show up for you, the Java version can be manually changed. Navigate to the “Startup” tab of your server, select `Java 25` from the “Docker Image” dropdown as shown in the image below. ![Pterodactyl Manual Java Version Change](https://docs.papermc.io/_astro/pterodactyl-manual.BuJx9SUE_21JnCB.webp) The Verifying Installation section does not apply for Pterodactyl. Verifying installation ---------------------- [Section titled “Verifying installation”](https://docs.papermc.io/misc/java-install/#verifying-installation) Now that you have installed Java 25, run this command in your terminal to ensure the process was successful. java -version The output should be similar to this. The important parts to look out for is that it starts with `openjdk 25` and contains `64-Bit` in the last line. If the output you get is similar to `java: command not found`, try creating a new terminal session. openjdk version "25" 2025-09-16OpenJDK Runtime Environment (build 25+36-3489)OpenJDK 64-Bit Server VM (build 25+36-3489, mixed mode, sharing) If your installation has failed, do not hesitate to reach out in the `#paper-help` channel of our [Discord](https://discord.gg/papermc) for support. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Localization | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/localization/#_top) Localization ============ Adventure provides a way to utilize Minecraft’s built-in localization system for client-side translations as well as an additional Adventure-specific system for translating text. Using Minecraft’s localization ------------------------------ [Section titled “Using Minecraft’s localization”](https://docs.papermc.io/adventure/localization/#using-minecrafts-localization) To send text to a player that will be translated in the language they have selected in their client settings, use a translatable component. For example, `Component.translatable("block.minecraft.diamond_block")` will render as “Block of Diamond” (or translated to another language) when viewed by the client. Some translation keys have arguments which are inserted into the translated content. For example, `Component.translatable("block.minecraft.player_head.named", Component.text("Mark"))` will render as “Mark’s Head”. Translatable components can have styling, hover/click events and children components just like any other component type. ### Resource pack language files [Section titled “Resource pack language files”](https://docs.papermc.io/adventure/localization/#resource-pack-language-files) You can provide translation files in a resource pack in order to change existing translations or add new ones. For a guide on how to do that, see the [Minecraft Wiki](https://minecraft.wiki/w/Resource_pack#Language) . ### Using Adventure’s localization [Section titled “Using Adventure’s localization”](https://docs.papermc.io/adventure/localization/#using-adventures-localization) Adventure also provides a way to handle localization in Adventure itself. This can be useful in environments where you do not have access to resource packs, or wish to do translations yourself, without relying on Minecraft’s translation system. Any component that is sent to a client is ran through the `GlobalTranslator` using the locale of the client. This means that if you wish to have automatic translation of components using your own translation data, you can add a `Translator` to the `GlobalTranslator`. You can either provide your own implementation of `Translator` or use one of the implementations that Adventure provides. Once you have a `Translator` instance, you can register it to the `GlobalTranslator` using `GlobalTranslator.translator().addSource(myTranslator)`. This will then make it available for automatic translation across the platform. Using a custom `Translator` --------------------------- [Section titled “Using a custom Translator”](https://docs.papermc.io/adventure/localization/#using-a-custom-translator) A `Translator` is a simple interface that provides two ways of translating content. The first `translate` method provides the translation key and locale as an argument and expects a nullable `MessageFormat` in return. This system is comparable to Minecraft’s built-in localization system, using the standard Java [message format](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/text/MessageFormat.html) for arguments. If the first `translate` method returns `null`, the second method which provides the translatable component and locale as an argument can be used. This method allows for much richer customization of the translation process as you can return an entire component. This means you can, for example, customize the color and styling of the translated component, rather than relying solely on strings for the message format system. Below is an example of how one might implement a custom `Translator`. public class MyTranslator implements Translator { @Override public @NotNull Key name() { // Every translator has a name which is used to identify this specific translator instance. return Key.key("mynamespace:mykey"); } @Override public @Nullable MessageFormat translate(final @NotNull String key, final @NotNull Locale locale) { // You could retrieve a string from a properties file, a config file, or some other system. // An an example, we will hard-code a check for a specific key here. if (key.equals("mytranslation.key") && locale == Locale.US) { return new MessageFormat("Hello %s!", locale); } else { // If you only want to use component translation, you can override this method and always return `null`. return null; } } @Override public @Nullable Component translate(@NotNull TranslatableComponent component, @NotNull Locale locale) { // As above, we will hardcode a check here, but you should be reading this from elsewhere. if (key.equals("mytranslation.colorful") && locale == Locale.US) { return Component.text("Hello, ", NamedTextColor.GREEN) .append(component.arguments().get(0).color(NamedTextColor.RED)) .append(component.children()); // Always make sure to copy the children over! } else { return null; } }} ### Using a `TranslationStore` [Section titled “Using a TranslationStore”](https://docs.papermc.io/adventure/localization/#using-a-translationstore) A `TranslationStore` is a store of translations. It provides a simpler way creating a `Translator` without having to implement the logic for determining and storing translations yourself. You can create a translation store and then add or remove translations at will, even after registering it to the global translator. Adventure provides two translation stores, one for message format translating and one for component translating. An example of how to use a translation store is below. // As above, every translator needs an identifying name!// Could also use TranslationStore#component(Key) to work with components instead.final TranslationStore myStore = TranslationStore.messageFormat(Key.key("mynamespace:mykey")); // You can add translations one-by-one, or in bulk. Consult the Javadocs for a full list of methods.myStore.register("mytranslation.key", Locale.US, new MessageFormat("Hello %s!", Locale.US)); // You can then register this to the global translator so the translations are available there!GlobalTranslator.translator().addSource(myStore); There are additional methods on the message format translation store to bulk register from [resource bundles](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/ResourceBundle.html) . ### Using MiniMessage for translations [Section titled “Using MiniMessage for translations”](https://docs.papermc.io/adventure/localization/#using-minimessage-for-translations) Adventure also provides a translator that can use MiniMessage strings, with automatic support for placeholders and arguments. For more information, see [MiniMessage Translator](https://docs.papermc.io/adventure/minimessage/translator) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Migrating from Adventure 4.x to 5.x | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/migration/adventure-4.x/#_top) Migrating from Adventure 4.x to 5.x =================================== With the release of Adventure 5.0, some breaking changes have been introduced from the Adventure 4.x series. This page documents the changes made and how you as a developer can migrate your code. A modern codebase ----------------- [Section titled “A modern codebase”](https://docs.papermc.io/adventure/migration/adventure-4.x/#a-modern-codebase) One of the main goals for Adventure 5.0 was to migrate to a more modern codebase. The minimum version of Java required to use Adventure is now Java 21. By updating to Java 21, Adventure has taken advantage of sealed classes and interfaces. Almost every interface/class that was annotated with `@ApiStatus.NonExtendable` has now been made sealed. This means that you can no longer extend these classes, although you shouldn’t have been doing that in the first place! One relatively common incorrect usage was to create custom `Component` implementations. This is now no longer possible, and you should instead be using the `VirtualComponent` API. Another side effect of wanting a modern codebase is that the `adventure-extra-kotlin` module has been removed. This module will be re-introduced in a separate repo under a new module in the future. This will allow for more flexibility working around the more frequent Kotlin updates. The `adventure-text-serializer-gson-legacy-impl` module has also been removed. This module has been replaced with the implementation-agnostic `adventure-text-serializer-json-legacy-impl` module. Finally, Adventure now contains proper `module-info.java` files for those of you using the Java 9+ module system. Updated dependencies -------------------- [Section titled “Updated dependencies”](https://docs.papermc.io/adventure/migration/adventure-4.x/#updated-dependencies) Many non-breaking updates to dependencies have been made. There are a few notable breaking/major changes that are documented below. Adventure has migrated to using JSpecify for nullness annotations. These are applied at a package/class level, so unless otherwise specified, everything should be treated as non-null. As most of the internal implementation of Adventure is now using records, we no longer need to use the Examination library for `toString` generation. The Examination library has been entirely removed from Adventure and is no longer a transitive dependency. The `adventure-text-logger-slf4j` module has been updated to use SLF4J 2.0. The GSON library has been updated to 2.13.2. Although this version is higher than most Minecraft versions that are supported by Adventure, it is not our intention to drop support for these older versions. We will endeavor to not use newer GSON features that would break support for older versions of GSON used in legacy Minecraft versions. Breaking changes ---------------- [Section titled “Breaking changes”](https://docs.papermc.io/adventure/migration/adventure-4.x/#breaking-changes) ### Click event changes [Section titled “Click event changes”](https://docs.papermc.io/adventure/migration/adventure-4.x/#click-event-changes) The `ClickEvent` class is now a typed interface. The type argument for this click event is the payload type. This does not change how you construct click events but does make serialization and deserialization easier. This change also extends to `ClickEvent$Action`, which is now no longer an enum and instead is a typed interface. Additionally, the `nbt` field for custom click event payloads is now nullable. This is to allow for the possibility of custom click events without NBT and to be more in line with Vanilla Minecraft behavior. ### Component renderer changes [Section titled “Component renderer changes”](https://docs.papermc.io/adventure/migration/adventure-4.x/#component-renderer-changes) With the addition of the new object component, the `AbstractComponentRenderer` interface has been updated to include a new method to render object components. This is a breaking change, as implementations of this method will be required. Going forward, we will be adding new methods to this class whenever Mojang adds new component types. This breaking change is documented in the `AbstractComponentRenderer` javadocs. ### Sealing of `TextFormat` interface [Section titled “Sealing of TextFormat interface”](https://docs.papermc.io/adventure/migration/adventure-4.x/#sealing-of-textformat-interface) Although it was never recommended to extend `TextFormat`, it was possible to do so in the past. This ability has been removed from the API, and the interface is now sealed. If you were extending this interface, you should instead consider extending the `StyleBuilderApplicable` interface for a more powerful and widely-used alternative. ### Chat type changes [Section titled “Chat type changes”](https://docs.papermc.io/adventure/migration/adventure-4.x/#chat-type-changes) Due to changes in the chat system, specifically around the creation of dynamic chat types, it is possible for chat types to not be keyed. Due to this internal change, `ChatType#key` is now nullable. Additionally, the class no longer implemented `Keyed`. Removal of deprecated methods and classes ----------------------------------------- [Section titled “Removal of deprecated methods and classes”](https://docs.papermc.io/adventure/migration/adventure-4.x/#removal-of-deprecated-methods-and-classes) A number of methods and classes have been deprecated in across the Adventure 4.x series. This section documents the removals that have been made and how you can migrate your code, if applicable. * **`BuildableComponent` has been removed.** You can now obtain a `ComponentBuilder` directly from a `Component` using `Component#toBuilder`. A breaking side effect of this change is that `NBTComponent` now only accepts one type argument, rather than two. * **Legacy chat signing/identifying methods have been removed.** Although legacy versions still use these features, they did not have enough usage to warrant their continued existence in Adventure. Generally speaking, you should migrate to using signed messages if you intend to send identified/chat messages. * **The `MessageType` enum has been removed entirely.** Chat messages are now identified when sending a signed message. All other messages are system messages. * **All `Audience#sendMessage` methods that accept an `Identity` or `Identified` have been removed.** Prefer sending signed messages instead. * **Boss bar percent has been removed.** This includes the max/min percent constants and methods to change/get the percent. You should instead be using the progress constants/methods. * **`of` style static methods have been removed.** These methods have been deprecated for some time, and each has named replacements. * **Custom click payload data has been removed.** As custom click payloads contain NBT, you should instead be using the `nbt` method. This includes the custom click event constructor methods that accept strings instead of NBT. * **`ClickEvent#create(Action, String)` has been removed.** As click events can now hold data other than strings, this method has been removed. If you were using this method, you should migrate to the `create` method that accepts a payload or use the direct construct methods (e.g. `ClickEvent#openUrl(String)`). * **`ClickEvent#value` has been removed.** As noted above, click events can now hold data other than strings. Therefore, this method has been removed in favor of the `payload` method. * **`AbstractComponent` has been removed.** As this class was primarily an implementation detail, it has been removed with no replacement. * **Non-builder component joining has been removed.** This includes the `Component#join` family of methods that do not accept a `JoinConfiguration`. You should instead be using `Component#textOfChildren` or `join` methods that accept a `JoinConfiguration`. * **`Component#detectCycle(Component)` has been removed.** As components are immutable, this method is not required and has therefore been removed with no replacement. * **Non-builder component text replacement has been removed.** This includes the `Component#replace[First]Text` family of methods that do not accept a `TextReplacementConfig`. You should instead be using the `replaceText` methods that accept a `TextReplacementConfig`. * **`TranslationRegistry` has been removed.** Registries have been replaced with the more powerful `TranslationStore`. See static methods on `TranslationStore` for a compatible replacement. * **`JSONComponentConstants` has been removed.** This has been replaced with `ComponentTreeConstants` from the `adventure-text-serializer-commons` module. * **`PlainComponentSerializer` has been removed.** This has been replaced with the equivalent `PlainTextComponentSerializer` class. * **`ClickEvent$Action#payloadType` has been removed.** As click event actions are now typed, this field is no longer required. * **`UTF8ResourceBundleControl` has been removed.** From Java 9 onwards, resource bundles are loaded using UTF-8 by default. Therefore, this class is no longer required. Instead of using this class, you can load properties files without any resource bundle control. * **Removal of methods from `GSONComponentSerializer`.** Since the addition of the options system to customize JSON serializers, the `downsampleColors` and `emitLegacyHoverEvent` options in the `GSONComponentSerializer` has been removed. You should instead use `EMIT_RGB` and `EMIT_HOVER_EVENT_TYPE` fields in `JSONOptions` respectively. Additionally, the `legacyHoverEventSerializer` that accepts a `LegacyHoverEventSerializer` from the GSON module has been removed in favor of the generic alternative in the JSON module. * **Typos have been removed.** Some incorrectly spelt/named methods, such as `Argument#numeric` and `ComponentSerializer#deseializeOrNull`, have been removed. These methods have been deprecated, and correctly spelt/named methods have been available for a while. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Hangar auto-publishing | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/hangar-publishing/#_top) Hangar auto-publishing ====================== If you want to automatically publish your plugin to [Hangar](https://hangar.papermc.io/) on pushes, you can use our [Gradle plugin](https://github.com/HangarMC/hangar-publish-plugin) . After you have added the required `hangarPublish` configuration, you can manually publish it by running `./gradlew build publishPluginPublicationToHangar`, or have GitHub Actions automatically publish a version on every commit. Prerequisites ------------- [Section titled “Prerequisites”](https://docs.papermc.io/misc/hangar-publishing/#prerequisites) ### Gradle [Section titled “Gradle”](https://docs.papermc.io/misc/hangar-publishing/#gradle) Your plugin project needs to use Gradle as its build tooling. ### Creating the `Snapshot` release channel [Section titled “Creating the Snapshot release channel”](https://docs.papermc.io/misc/hangar-publishing/#creating-the-snapshot-release-channel) The builds script below will publish non-release builds under a `Snapshot` channel. You need to create this channel in your Hangar project’s channel page first. ![Create a Snapshot channel](https://docs.papermc.io/_astro/hangar-create-snapshot-channel.B_yTiJwe_Z2q8qIz.webp) ### Adding the `HANGAR_API_TOKEN` repository secret [Section titled “Adding the HANGAR\_API\_TOKEN repository secret”](https://docs.papermc.io/misc/hangar-publishing/#adding-the-hangar_api_token-repository-secret) First, you need to create a Hangar API token. Go to your Hangar settings in the profile dropdown and click on “Api keys” on the left. Then, tick the `create_version` permission box, give the key a name and create it. **At the top**, you should be given your secret API token. **Do not share this with anyone**; you will need it in the next step. The GitHub Actions workflow provided uses a repository secret to store your Hangar API key. Go to your GitHub project settings, then click on “Actions” under the Security tab and click the “New repository secret” button. Name the secret `HANGAR_API_TOKEN` and paste the Hangar API token from the previous step into the Secret field. ![Action secrets](https://docs.papermc.io/_astro/github-secrets-actions.A6sV3nER_1UOtdf.webp) Project files ------------- [Section titled “Project files”](https://docs.papermc.io/misc/hangar-publishing/#project-files) The files below are simple examples that require little manual changes for you to use, but you can still adapt them depending on your needs. Take a look at the comments and especially the TODOs to figure out what you still need to change. ### `gradle.properties` [Section titled “gradle.properties”](https://docs.papermc.io/misc/hangar-publishing/#gradleproperties) Create a `gradle.properties` file in your project root directory if it does not already exist. In there, you define the platform versions your plugin is compatible with. Simply remove the platforms you don’t need and put in the correct versions. Hangar allows version ranges (such as `1.19-1.20.2`) and wildcards (such as `1.20.x`). # Specify the platform versions for Paper and Velocity.# Hangar also allows version ranges (such as 1.19-1.20.2) and wildcards (such as 1.20.x).# TODO: Remove the platforms you don't need and put in the correct versions.paperVersion=1.12.2, 1.16.5, 1.19-1.20.2velocityVersion=3.2waterfallVersion=1.20 ### `build.gradle.kts` [Section titled “build.gradle.kts”](https://docs.papermc.io/misc/hangar-publishing/#buildgradlekts) In the plugins block of your `build.gradle.kts` build script, add the publish plugin: plugins { id("io.papermc.hangar-publish-plugin") version "0.1.2"} Then you simply need to add the `hangarPublish` configuration block and make sure you do the following: * If your plugin is not a Paper plugin, or supports Velocity/Waterfall as well, copy the register block with a different platform and change the property used instead of `paperVersion` (as declared in the `gradle.properties` file). * Insert the correct project namespace * Insert your plugin dependencies, if any * You need to have the `HANGAR_API_TOKEN` repository secret set up if you are using the Actions file below, otherwise add the API key in some other way. import io.papermc.hangarpublishplugin.model.Platforms // ... hangarPublish { publications.register("plugin") { version.set(project.version as String) channel.set("Snapshot") // We're using the 'Snapshot' channel // TODO: Edit the project name to match your Hangar project id.set("hangar-project") apiKey.set(System.getenv("HANGAR_API_TOKEN")) platforms { // TODO: Use the correct platform(s) for your plugin register(Platforms.PAPER) { // TODO: If you're using ShadowJar, replace the jar lines with the appropriate task: // jar.set(tasks.shadowJar.flatMap { it.archiveFile }) // Set the JAR file to upload jar.set(tasks.jar.flatMap { it.archiveFile }) // Set platform versions from gradle.properties file val versions: List = (property("paperVersion") as String) .split(",") .map { it.trim() } platformVersions.set(versions) // TODO: Configure your plugin dependencies, if any dependencies { // Example for a dependency found on Hangar hangar("Maintenance") { required.set(false) } // Example for an external dependency url("Debuggery", "https://github.com/PaperMC/Debuggery") { required.set(true) } } } } }} GitHub Actions workflow ----------------------- [Section titled “GitHub Actions workflow”](https://docs.papermc.io/misc/hangar-publishing/#github-actions-workflow) You don’t necessarily need to publish via GitHub Actions, but it is an easy way to do so. If you want to use it, create a `publish.yml` file in the `.github/workflows` directory of your project root folder and make sure you [add the repository secret](https://docs.papermc.io/misc/hangar-publishing/#adding-the-hangar_api_token-repository-secret) . You can add and remove branches to be published by editing the `branches` section. name: Publish to Hangaron: push: branches: # Add any additional branches you want to automatically publish from - main # Assuming your main branch is called 'main' jobs: publish: # TODO: Optional, make sure the task only runs on pushes to your repository and doesn't fail on forks. Uncomment the line below and put the repo owner into the quotes # if: github.repository_owner == '' runs-on: ubuntu-22.04 steps: - name: Checkout Repository uses: actions/checkout@v3 - name: Validate Gradle Wrapper uses: gradle/wrapper-validation-action@v1 - name: Set up JDK 17 uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: 17 - name: Publish env: # Make sure you have added a repository secret in the repository's settings HANGAR_API_TOKEN: ${{ secrets.HANGAR_API_TOKEN }} run: ./gradlew build publishPluginPublicationToHangar --stacktrace Optional: Handling multiple channels and an automatic changelog --------------------------------------------------------------- [Section titled “Optional: Handling multiple channels and an automatic changelog”](https://docs.papermc.io/misc/hangar-publishing/#optional-handling-multiple-channels-and-an-automatic-changelog) With the following code, any version that contains a hyphen (`-`) will be published under the `Snapshot` channel (that you need to create on Hangar) and the others on the `Release` channel. By editing the `channel.set(...)` line, you can change this to any channel you would like. For example, you could further split builds depending on the branch you are currently on into `Alpha` builds. import java.io.ByteArrayOutputStream // ... // Helper methodsfun executeGitCommand(vararg command: String): String { val byteOut = ByteArrayOutputStream() exec { commandLine = listOf("git", *command) standardOutput = byteOut } return byteOut.toString(Charsets.UTF_8.name()).trim()} fun latestCommitMessage(): String { return executeGitCommand("log", "-1", "--pretty=%B")} val versionString: String = version as Stringval isRelease: Boolean = !versionString.contains('-') val suffixedVersion: String = if (isRelease) { versionString} else { // Give the version a unique name by using the GitHub Actions run number versionString + "+" + System.getenv("GITHUB_RUN_NUMBER")} // Use the commit description for the changelogval changelogContent: String = latestCommitMessage() // If you would like to publish releases with their proper changelogs manually, simply add an if statement with the `isRelease` variable here.hangarPublish { publications.register("plugin") { version.set(suffixedVersion) channel.set(if (isRelease) "Release" else "Snapshot") changelog.set(changelogContent) // ... (see above) }} Optional: Updating the resource page ------------------------------------ [Section titled “Optional: Updating the resource page”](https://docs.papermc.io/misc/hangar-publishing/#optional-updating-the-resource-page) A notable part of publishing a new version might be updating the resource page (e.g. the plugin’s home page) with new content from your plugin’s repository. In this example, we’re using a README file, but you can use any text you want, as long as it is in Markdown format. val pageContent = project.file("README.md").readText() hangarPublish { publications.register("plugin") { // ... (see above) pages.resourcePage(pageContent) }} You can invoke the `syncPluginPublicationMainResourcePagePageToHangar` task to update the resource page on Hangar. This will not publish a new version, but simply update the page content on Hangar. If you’re using a GitHub Actions workflow, you should also add the task invocation to the `Publish` step in your workflow: - name: Publish # ... run: ./gradlew build publishPluginPublicationToHangar syncPluginPublicationMainResourcePagePageToHangar --stacktrace Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Migration | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/migration/#_top) Migration ========= These guides provide advice and replacements useful when migrating to the latest version of Adventure. This includes migrating from older versions of Adventure, as well as migrating from other libraries. * [Migrating from Adventure 4.x to 5.x](https://docs.papermc.io/adventure/migration/adventure-4.x) * [A modern codebase](https://docs.papermc.io/adventure/migration/adventure-4.x#a-modern-codebase) * [Updated dependencies](https://docs.papermc.io/adventure/migration/adventure-4.x#updated-dependencies) * [Breaking changes](https://docs.papermc.io/adventure/migration/adventure-4.x#breaking-changes) * [Removal of deprecated methods and classes](https://docs.papermc.io/adventure/migration/adventure-4.x#removal-of-deprecated-methods-and-classes) * [Migrating from the BungeeCord Chat API](https://docs.papermc.io/adventure/migration/bungeecord-chat-api) * [Audiences](https://docs.papermc.io/adventure/migration/bungeecord-chat-api#audiences) * [Decoration and styling](https://docs.papermc.io/adventure/migration/bungeecord-chat-api#decoration-and-styling) * [Chat colors](https://docs.papermc.io/adventure/migration/bungeecord-chat-api#chat-colors) * [Differences in `ComponentBuilder`](https://docs.papermc.io/adventure/migration/bungeecord-chat-api#differences-in-componentbuilder) * [Immutability](https://docs.papermc.io/adventure/migration/bungeecord-chat-api#immutability) * [Serializers](https://docs.papermc.io/adventure/migration/bungeecord-chat-api#serializers) * [Backwards compatibility](https://docs.papermc.io/adventure/migration/bungeecord-chat-api#backwards-compatibility) * [Migrating from text 3.x](https://docs.papermc.io/adventure/migration/text-3.x) * [A word of caution](https://docs.papermc.io/adventure/migration/text-3.x#a-word-of-caution) * [Breaking changes from text 3.x](https://docs.papermc.io/adventure/migration/text-3.x#breaking-changes-from-text-3x) * [Serializer](https://docs.papermc.io/adventure/migration/text-3.x#serializer) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Migrating from text 3.x | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/migration/text-3.x/#_top) Migrating from text 3.x ======================= Adventure is an evolution of the text 3.x API. If you’ve worked with the text API before, the switch to Adventure should be relatively quick. For the most part, you’ll just need to depend on the Adventure API and the relevant [Platform](https://docs.papermc.io/adventure/platform) you support and replace references to classes in `net.kyori.text` to `net.kyori.adventure.text`, though see below for major breaking changes. A word of caution ----------------- [Section titled “A word of caution”](https://docs.papermc.io/adventure/migration/text-3.x/#a-word-of-caution) However, before you continue, it is strongly recommended you read about [Audiences](https://docs.papermc.io/adventure/audiences) . Unlike text, Adventure defines a standard interface for sending content (including chat messages) to viewers. In addition, Adventure defines interfaces for other game play mechanics that can be arbitrarily sent to players. Breaking changes from text 3.x ------------------------------ [Section titled “Breaking changes from text 3.x”](https://docs.papermc.io/adventure/migration/text-3.x/#breaking-changes-from-text-3x) ### Factory methods renamed [Section titled “Factory methods renamed”](https://docs.papermc.io/adventure/migration/text-3.x/#factory-methods-renamed) In text 3.x, components could be constructed using the `Component.of()` methods. In Adventure, we’ve changed to using `Component.(/*...*/)` style methods to allow for easier static imports. Similarly, `Style.of(/*...*/)` is changed to `Style.style(/*...*/)`. ### `.builder()` [Section titled “.builder()”](https://docs.papermc.io/adventure/migration/text-3.x/#builder) Builders are now created by calling the aforementioned factory methods with no parameters. For example, `TextComponent.builder()` becomes `Component.text()`. Note that the equivalent of `TextComponent.builder("hello")` is `Component.text().content("hello")`. ### `.append()` with a String argument [Section titled “.append() with a String argument”](https://docs.papermc.io/adventure/migration/text-3.x/#append-with-a-string-argument) Component builders in 3.x had a shorthand for appending a new text component: `builder.append("wow")`. In Adventure you have to write it in full, `builder.append(Component.text("wow"))` in this case. ### `LegacyComponentSerializer` [Section titled “LegacyComponentSerializer”](https://docs.papermc.io/adventure/migration/text-3.x/#legacycomponentserializer) In text 3.x, you would deserialize a component that used a color code prefix that differed from the section symbol normally used by using `LegacyComponentSerializer.legacy().deserialize(string, altChar)`. In Adventure, the API to use is `LegacyComponentSerializer.legacy(altChar).deserialize(string)`. To make a linking serializer you have to use the builder. Change `LegacyComponentSerializer.legacyLinking(style)` to `LegacyComponentSerializer.builder().extractUrl(style).build()`. ### `TextColor` renamed to `NamedTextColor` [Section titled “TextColor renamed to NamedTextColor”](https://docs.papermc.io/adventure/migration/text-3.x/#textcolor-renamed-to-namedtextcolor) In order to accommodate the new RGB colors introduced in 1.16, all the named text colors were moved to the `NamedTextColor` class. References to the old `TextColor` class should be updated to refer to `NamedTextColor`. Serializer ---------- [Section titled “Serializer”](https://docs.papermc.io/adventure/migration/text-3.x/#serializer) If you have a need to interoperate with clients using the old text 3.x API, you can use the `adventure-text-serializer-legacy-text3` artifact, which includes a `LegacyText3ComponentSerializer` that can convert from Adventure to text 3.x components and back. Note that RGB colors will be downsampled. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Downloads Service | PaperMC Docs [Skip to content](https://docs.papermc.io/misc/downloads-service/#_top) Downloads Service ================= PaperMC provides a downloads service to facilitate automated downloads access. Full documentation can be found on the [Downloads Service Docs](https://fill.papermc.io/swagger-ui/index.html#/) . All requests must now include a valid User-Agent header that: * Clearly identifies your software or company * Is not generic (e.g. curl, wget, or similar defaults) * Includes a contact URL or email address (e.g. a homepage, bot info page, or support email) **Some examples:** mc-image-helper/1.39.11 (https://github.com/itzg/docker-minecraft-server)nodecraft/packifier/1.0.0 ([email protected]) REST API examples ----------------- [Section titled “REST API examples”](https://docs.papermc.io/misc/downloads-service/#rest-api-examples) ### Getting the latest version [Section titled “Getting the latest version”](https://docs.papermc.io/misc/downloads-service/#getting-the-latest-version) #!/usr/bin/env sh PROJECT="paper"USER_AGENT="cool-project/1.0.0 ([email protected])" LATEST_VERSION=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT} | \ jq -r '.versions | to_entries[0] | .value[0]') echo "Latest version is $LATEST_VERSION" This will get the latest available Minecraft version for the given project. ### Getting the latest stable build number [Section titled “Getting the latest stable build number”](https://docs.papermc.io/misc/downloads-service/#getting-the-latest-stable-build-number) #!/usr/bin/env sh PROJECT="paper"MINECRAFT_VERSION="26.1.2"USER_AGENT="cool-project/1.0.0 ([email protected])" LATEST_BUILD=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT}/versions/${MINECRAFT_VERSION}/builds | \ jq -r 'map(select(.channel == "STABLE")) | .[0] | .id') if [ "$LATEST_BUILD" != "null" ]; then echo "Latest stable build is $LATEST_BUILD"else echo "No stable build for version $MINECRAFT_VERSION found :("fi This will get the latest stable build for the given project and Minecraft version, if it’s available. ### Downloading the latest stable build [Section titled “Downloading the latest stable build”](https://docs.papermc.io/misc/downloads-service/#downloading-the-latest-stable-build) #!/usr/bin/env sh PROJECT="paper"MINECRAFT_VERSION="26.1.2"USER_AGENT="cool-project/1.0.0 ([email protected])" # First check if the requested version has a stable buildBUILDS_RESPONSE=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT}/versions/${MINECRAFT_VERSION}/builds) # Check if the API returned an errorif echo "$BUILDS_RESPONSE" | jq -e '.ok == false' > /dev/null 2>&1; then ERROR_MSG=$(echo "$BUILDS_RESPONSE" | jq -r '.message // "Unknown error"') echo "Error: $ERROR_MSG" exit 1fi # Try to get a stable build URL for the requested versionPAPERMC_URL=$(echo "$BUILDS_RESPONSE" | jq -r 'first(.[] | select(.channel == "STABLE") | .downloads."server:default".url) // "null"')FOUND_VERSION="$MINECRAFT_VERSION" # If no stable build for requested version, find the latest version with a stable buildif [ "$PAPERMC_URL" == "null" ]; then echo "No stable build for version $MINECRAFT_VERSION, searching for latest version with stable build..." # Get all versions for the project (using the same endpoint structure as the "Getting the latest version" example) # The versions are organized by version group, so we need to extract all versions from all groups # Then sort them properly as semantic versions (newest first) VERSIONS=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT} | \ jq -r '.versions | to_entries[] | .value[]' | \ sort -V -r) # Iterate through versions to find one with a stable build for VERSION in $VERSIONS; do VERSION_BUILDS=$(curl -s -H "User-Agent: $USER_AGENT" https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds) # Check if this version has a stable build STABLE_URL=$(echo "$VERSION_BUILDS" | jq -r 'first(.[] | select(.channel == "STABLE") | .downloads."server:default".url) // "null"') if [ "$STABLE_URL" != "null" ]; then PAPERMC_URL="$STABLE_URL" FOUND_VERSION="$VERSION" echo "Found stable build for version $VERSION" break fi donefi if [ "$PAPERMC_URL" != "null" ]; then # Download the latest Paper version curl -o server.jar $PAPERMC_URL echo "Download completed (version: $FOUND_VERSION)"else echo "No stable builds available for any version :(" exit 1fi This is the most common use case for the API. It will download the latest stable build for the given project and Minecraft version. You should always serve & use the stable builds. Experimental builds are prone to error and do not receive support. GraphQL API examples -------------------- [Section titled “GraphQL API examples”](https://docs.papermc.io/misc/downloads-service/#graphql-api-examples) Fill also supports a GraphQL API, which can be accessed at `https://fill.papermc.io/graphql`. Fill’s GraphQL API uses standard pagination, which you can learn more about [here](https://graphql.org/learn/pagination/) . A built-in GraphQL playground is available at [https://fill.papermc.io/graphiql?path=/graphql](https://fill.papermc.io/graphiql?path=/graphql) . Common API tools such as Postman will introspect the API and provide a UI for building queries. ### Getting the latest version [Section titled “Getting the latest version”](https://docs.papermc.io/misc/downloads-service/#getting-the-latest-version-1) query LatestVersion { project(key: "paper") { key versions(first: 1, orderBy: {direction: DESC}) { edges { node { key } } } }} Example response { "data": { "project": { "key": "paper", "versions": { "edges": [ { "node": { "key": "1.21.11" } } ] } } }} ### Getting the latest stable build number [Section titled “Getting the latest stable build number”](https://docs.papermc.io/misc/downloads-service/#getting-the-latest-stable-build-number-1) query LatestStableBuild { project(key: "paper") { key versions(first: 1, orderBy: {direction: DESC}) { edges { node { key builds(filterBy: { channel: STABLE }, first: 1, orderBy: { direction: DESC }) { edges { node { number } } } } } } }} Example response { "data": { "project": { "key": "paper", "versions": { "edges": [ { "node": { "key": "1.21.10", "builds": { "edges": [ { "node": { "number": 48 } } ] } } } ] } } }} ### Getting the latest stable build download URL [Section titled “Getting the latest stable build download URL”](https://docs.papermc.io/misc/downloads-service/#getting-the-latest-stable-build-download-url) query LatestStableBuildDownloadURL { project(key: "paper") { key versions(first: 1, orderBy: {direction: DESC}) { edges { node { key builds(filterBy: { channel: STABLE }, first: 1, orderBy: { direction: DESC }) { edges { node { number download(key: "server:default") { name url checksums { sha256 } size } } } } } } } }} Example response { "data": { "project": { "key": "paper", "versions": { "edges": [ { "node": { "key": "1.21.10", "builds": { "edges": [ { "node": { "number": 48, "download": { "name": "paper-1.21.10-48.jar", "url": "https://fill-data.papermc.io/v1/objects/bfca155b4a6b45644bfc1766f4e02a83c736e45fcc060e8788c71d6e7b3d56f6/paper-1.21.10-48.jar", "checksums": { "sha256": "bfca155b4a6b45644bfc1766f4e02a83c736e45fcc060e8788c71d6e7b3d56f6" }, "size": 54185955 } } } ] } } } ] } } }} Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # MiniMessage | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/minimessage/#_top) MiniMessage =========== The MiniMessage format is a simple string representation of chat components, designed to be easy for end users to learn, and for developers to extend. Hello world, isn't MiniMessage fun? If you’re looking to write messages with MiniMessage, take a look at the [MiniMessage Format](https://docs.papermc.io/adventure/minimessage/format) , or if you’re looking to develop software that uses MiniMessage, take a look at the [API overview](https://docs.papermc.io/adventure/minimessage/api) . * [Format](https://docs.papermc.io/adventure/minimessage/format) * [API](https://docs.papermc.io/adventure/minimessage/api) * [Dynamic replacements](https://docs.papermc.io/adventure/minimessage/dynamic-replacements) * [MiniMessage translator](https://docs.papermc.io/adventure/minimessage/translator) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Configuration | PaperMC Docs [Skip to content](https://docs.papermc.io/waterfall/configuration/#_top) We recommend you transition to [Velocity](https://papermc.io/software/velocity) . For more information, see the [announcement](https://forums.papermc.io/threads/1088/) . Configuration ============= This page details the various configuration settings exposed by Waterfall. These settings can be found in waterfall.yml. If you want information on settings in BungeeCord’s config.yml, you should see its respective documentation pages. use\_netty\_dns\_resolver: true[#](https://docs.papermc.io/waterfall/configuration/#use_netty_dns_resolver) Sets whether Netty”s async DNS resolver is used for account authentication. disable\_modern\_tab\_limiter: true[#](https://docs.papermc.io/waterfall/configuration/#disable_modern_tab_limiter) Disables the tab completion limit for 1.13+ clients. log\_initial\_handler\_connections: true[#](https://docs.papermc.io/waterfall/configuration/#log_initial_handler_connections) Sets whether to log InitialHandler connections. throttling: 1000[#](https://docs.papermc.io/waterfall/configuration/#throttling) How often tab-complete packets can be sent in milliseconds. game\_version: ""[#](https://docs.papermc.io/waterfall/configuration/#game_version) The supported versions displayed to the client. Default is a comma separated list of supported versions. For example 1.8.x, 1.9.x, 1.10.x disable\_tab\_list\_rewrite: true[#](https://docs.papermc.io/waterfall/configuration/#disable_tab_list_rewrite) This setting disables tablist rewriting, which may resolve issues setting player profiles when Waterfall is in offline mode. disable\_entity\_metadata\_rewrite: false[#](https://docs.papermc.io/waterfall/configuration/#disable_entity_metadata_rewrite) This setting disables entity metadata rewriting in favor of sending a join packet to the client. It offers a more robust solution for modded environments but can cause plugins to break. plugin\_channel\_name\_limit: 128[#](https://docs.papermc.io/waterfall/configuration/#plugin_channel_name_limit) The maximum channel identifier length. May be useful for certain broken mods. registered\_plugin\_channels\_limit: 128[#](https://docs.papermc.io/waterfall/configuration/#registered_plugin_channels_limit) The maximum number of registered plugin channels for a connection. Used by mods and some plugins. May be useful to fix certain broken modpacks. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Waterfall Documentation | PaperMC Docs [Skip to content](https://docs.papermc.io/waterfall/#_top) We recommend you transition to [Velocity](https://papermc.io/software/velocity) . For more information, see the [announcement](https://forums.papermc.io/threads/1088/) . Waterfall Documentation ======================= Waterfall is the BungeeCord fork that aims to improve performance and stability. [Getting started](https://docs.papermc.io/waterfall/getting-started) How to get started with running Waterfall. [Configuration](https://docs.papermc.io/waterfall/configuration) Configuration guide for Waterfall. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Migrating from the BungeeCord Chat API | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#_top) Migrating from the BungeeCord Chat API ====================================== Adventure’s text API and the BungeeCord Chat API are designed along very different methodologies. This page goes over some notable differences. Audiences --------- [Section titled “Audiences”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#audiences) It is strongly recommended you read about [Audiences](https://docs.papermc.io/adventure/audiences) first. Unlike BungeeCord, which limits functionality to specific user types, Adventure allows only the specific operations that apply to an audience to be taken. Decoration and styling ---------------------- [Section titled “Decoration and styling”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#decoration-and-styling) The BungeeCord Chat API stores all decorations in the `BaseComponent`. Adventure separates out styles into their own `Style` class. BungeeCord allows you to merge the styles from one component into another. Adventure provides equivalent methods that merge styles together, or allows you to replace the styles on one component with another. Chat colors ----------- [Section titled “Chat colors”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#chat-colors) Adventure’s chat color and styling hierarchy differs from that of BungeeCord’s `ChatColor` API. This is probably where the most stark contrast between the Adventure API and BungeeCord/Bukkit will manifest. ### Replacement for `ChatColor` [Section titled “Replacement for ChatColor”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#replacement-for-chatcolor) Adventure’s equivalents for `ChatColor` are split over three types: * Formatting types (such as `BOLD` or `ITALIC`) are in `TextDecoration`, and can be set on a component or a style with the `decoration` method. Decorations also use a tristate to specify if they are enabled, disabled, or not set (in which case the component inherits the setting from its parent component). * Named colors (also called the legacy Mojang color codes) now exist in the `NamedTextColor` class. * RGB colors are constructed using the `TextColor.color()` methods (this is equivalent to the `ChatColor.of()` method in the BungeeCord `ChatColor` 1.16 API. ### Legacy strings can’t be constructed [Section titled “Legacy strings can’t be constructed”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#legacy-strings-cant-be-constructed) The BungeeCord `ChatColor` API’s heritage is in the Bukkit API. The Bukkit `ChatColor` API in turn dates from the early days of Minecraft (Beta 1.0), when the normal and accepted way of sending formatted messages to the client was to concatenate magical strings that told the client what to format. A formatted chat message would be sent to the client like this: player.sendMessage(ChatColor.GREEN + "Hi everyone, " + ChatColor.BOLD + "this message is in green and bold" + ChatColor.RESET + ChatColor.GREEN + "!"); This style of sending messages has persisted to this day, even as Mojang introduced rich chat components into Minecraft 1.7.2. Bukkit preserved this backwards-compatible behavior, and BungeeCord introduced the change as a result of being compatible with the Bukkit `ChatColor` class. In Adventure, you can’t concatenate magical formatting codes. The equivalent of `ChatColor` in Adventure, `TextColor`, instead returns descriptive text describing the color when its `toString()` is called. The recommended replacement is to convert all legacy messages to components. ### `ChatColor.stripColor()` [Section titled “ChatColor.stripColor()”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#chatcolorstripcolor) `ChatColor.stripColor()` does not exist in Adventure. An equivalent would be to use `PlainTextComponentSerializer.plainText().serialize(LegacyComponentSerializer.legacySection().deserialize(input))`. ### `ChatColor.translateAlternateColorCodes()` [Section titled “ChatColor.translateAlternateColorCodes()”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#chatcolortranslatealternatecolorcodes) `ChatColor.translateAlternateColorCodes()` does not exist in Adventure. Instead you should use `LegacyComponentSerializer.legacy(altChar).deserialize(input)` when deserializing a legacy string. Differences in `ComponentBuilder` --------------------------------- [Section titled “Differences in ComponentBuilder”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#differences-in-componentbuilder) The BungeeCord `ComponentBuilder` treats each component independently and allows you to manually carry over styles from a prior component. In Adventure, there are multiple component builders. The closest equivalent for a BungeeCord `ComponentBuilder` is to append components to a top-level empty component using `Component.text()` as a base. To replicate the behavior of `ComponentBuilder`, consider doing the following: * Use the `Style` class to store common styles and the `mergeStyle` and `style` methods to merge and replace styles on a component. * Use the Adventure `TextComponent` builder to create one component at a time and then append to a top-level text component builder that is empty. As an example, this BungeeCord component: new ComponentBuilder("hello") .color(ChatColor.GOLD) .append(" world", FormatRetention.NONE) .build() becomes this Adventure equivalent: Component.text() .append(Component.text("hello", NamedTextColor.GOLD) .append(Component.text(" world")) .build() Likewise, new ComponentBuilder("hello") .color(ChatColor.GOLD) .bold(true) .append(" world") .build() becomes Style style = Style.style(NamedTextColor.GOLD, TextDecoration.BOLD);Component.text() .append(Component.text("hello", style) .append(Component.text(" world", style)) .build() Immutability ------------ [Section titled “Immutability”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#immutability) In the BungeeCord Chat API, all components are mutable. Adventure text components, however, are immutable - any attempt to change a component results in a new component being created that is a copy of the original component with the change you requested. Serializers ----------- [Section titled “Serializers”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#serializers) The BungeeCord Chat API includes three serializers. All three have equivalents in Adventure: * The `TextComponent.fromLegacyText()` deserialization method is equivalent to the `deserialize` method of the [Legacy](https://docs.papermc.io/adventure/serializer/legacy) text serializer. Likewise, the `BaseComponent.toLegacyText()` serialization method is equivalent to the `serialize` method on the legacy text serializer. * The `TextComponent.toPlainText()` serialization method is equivalent to the `serialize` method of the [Plain](https://docs.papermc.io/adventure/serializer/plain) text serializer. A component can be created from a plain-text string using `Component.text(string)` * The Adventure equivalent of `ComponentSerializer` is the [Gson](https://docs.papermc.io/adventure/serializer/gson) text serializer. Backwards compatibility ----------------------- [Section titled “Backwards compatibility”](https://docs.papermc.io/adventure/migration/bungeecord-chat-api/#backwards-compatibility) The `BungeeCordComponentSerializer` allows you to convert between Adventure [Components](https://docs.papermc.io/adventure/text) and the native BungeeCord chat component API and back. This can be used when native platform support is unavailable. The serializer is available in the `adventure-platform-text-serializer-bungeecord` artifact. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Getting started | PaperMC Docs [Skip to content](https://docs.papermc.io/waterfall/getting-started/#_top) We recommend you transition to [Velocity](https://papermc.io/software/velocity) . For more information, see the [announcement](https://forums.papermc.io/threads/1088/) . Getting started =============== What is Waterfall? ------------------ [Section titled “What is Waterfall?”](https://docs.papermc.io/waterfall/getting-started/#what-is-waterfall) Waterfall is a fork of BungeeCord, a proxy used primarily to teleport players between multiple Minecraft servers. Waterfall focuses on three main areas: * Stability: Waterfall aims to be stable. We will achieve this through making the code base testable and discouraging practices that lead to proxy lag. * Features: Waterfall aims to include more features than canonical BungeeCord. * Scalability: Waterfall should be able to handle a large number of concurrent players, given a reasonably modern CPU, memory, and good network connection. Requirements ------------ [Section titled “Requirements”](https://docs.papermc.io/waterfall/getting-started/#requirements) Waterfall requires **Java 8** or newer to run. The Paper team recommends you run on Java 11 or higher. Generally, LTS versions of Java are targeted, though you may have luck on newer versions. Migrating from BungeeCord ------------------------- [Section titled “Migrating from BungeeCord”](https://docs.papermc.io/waterfall/getting-started/#migrating-from-bungeecord) Waterfall is a drop in replacements for BungeeCord, you don’t need to make any changes to your configuration. Getting a proxy JAR ------------------- [Section titled “Getting a proxy JAR”](https://docs.papermc.io/waterfall/getting-started/#getting-a-proxy-jar) Paper provides runnable proxy JARs directly from our [downloads page](https://papermc.io/downloads/waterfall) . Click on the build number to download a file. Running the proxy ----------------- [Section titled “Running the proxy”](https://docs.papermc.io/waterfall/getting-started/#running-the-proxy) To run the proxy, simply start it up like any other Java application. Open your terminal, navigate to the saved location, and then run java -Xms512M -Xmx512M -jar waterfall-###.jar Aikar’s recommended flags for Waterfall are as follows: java -Xms512M -Xmx512M -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:+UnlockExperimentalVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -jar waterfall-###.jar The amount of memory can be set by changing the numbers in the `-Xms` and `-Xmx` flags. To configure your proxy, see the [configuration](https://docs.papermc.io/waterfall/configuration) page. Updating the proxy ------------------ [Section titled “Updating the proxy”](https://docs.papermc.io/waterfall/getting-started/#updating-the-proxy) To update the proxy, first stop it safely by executing the `end` command. Then replace the old proxy JAR with a new one, and start the proxy. That’s it. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Implementing platforms | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/implementing/#_top) Implementing platforms ====================== Most users will be here to look at information about existing platform implementations, but for those who are looking to build their own platform integrations, look no further. While at its core Adventure ‘just’ provides data structures and serializers, as the game evolves and more functionality is added there are more tunable options and platform hooks necessary to produce the correct output for the applicable game version. This has led to the introduction of a variety of services that platforms can provide implementations of using Java’s `ServiceLoader` mechanism. Some other behaviors are expected by convention. As there are not that many platforms that integrate with Adventure, this page is an attempt to cover the common points. Please don’t be afraid to ask us questions, and together we can work on fleshing out this page. Services -------- [Section titled “Services”](https://docs.papermc.io/adventure/platform/implementing/#services) ### `ComponentSerializer` services [Section titled “ComponentSerializer services”](https://docs.papermc.io/adventure/platform/implementing/#componentserializer-services) Most of the serializers (Gson, legacy, etc.) have `Provider` SPI’s that allow customizing the default behaviors of serializers. These are most applicable for the Gson/other JSON serializers where the data structures have changed over time, but the legacy serializer’s options can be worth referencing too. See the Javadoc for each serializer for more information. For any `JSONComponentSerializer` subtype, we have tried to gather relevant tunable options within a single system, keyed by the game’s active [data version](https://minecraft.wiki/w/Data_version) . To handle hover events in pre-1.16 game versions, there’s the additional `LegacyHoverEventSerializer` interface. We offer an implementation that uses `adventure-nbt` as a separate submodule, but platforms may wish to use a native NBT library for this instead. Both of these options should be set on builders in the appropriate `Provider` implementation. ### Data component values [Section titled “Data component values”](https://docs.papermc.io/adventure/platform/implementing/#data-component-values) To handle storing platform-specific data on `show_item` hover events, we expose opaque data objects in-API. Platforms should provide logic to convert between different implementations by providing an implementation of `DataComponentValueConverterRegistry.Provider`. For the most part this is just converting between platform-specific types and the generic `TagSerializable` and `Removed` types, but platforms should make sure to include converters to `GsonDataComponentValue` (from both platform types _and_ the generic `TagSerializable` that requires parsing SNBT for a conversion to occur). ### Click callbacks [Section titled “Click callbacks”](https://docs.papermc.io/adventure/platform/implementing/#click-callbacks) As callbacks are a commonly desired feature, Adventure provides a ‘virtual’ click event type for callback functions. This action is not persistent between runs, and needs platforms to register a command to trigger callbacks to execute. This is implemented via the `ClickCallback.Provider` SPI. This command should not be sent as part of the command tree that clients receive to avoid spamming them. Platforms implementing the click callback provider must register a command at the appropriate time, and maintain a registry of active callbacks that is added to any time a callback command is requested. The platform is responsible for ensuring any execution conditions apply and implementing the effects of any `Option`s that may be set on the callback. ### Component logging [Section titled “Component logging”](https://docs.papermc.io/adventure/platform/implementing/#component-logging) `ComponentLogger`, as part of the `adventure-text-logger-slf4j` module, provides a logging interface that extends SLF4J and wraps any existing SLF4J logger (compatible with v1 and v2). Platforms are responsible for providing the adapter that looks up the appropriate logger by name and serializes components to text. This should involve performing any translations if necessary. The default behavior of the logger is to serialize to plain text, but platforms may want to look at the `/serializer/ansi` serializer instead for colored output. ### Boss bars [Section titled “Boss bars”](https://docs.papermc.io/adventure/platform/implementing/#boss-bars) Boss bars are logistically somewhat complicated. As one of the few holders of mutable state in the library, they have to re-sync any state changes to their viewers. In order to track viewers and link up to any internal state, the `BossBarImplementation.Provider` SPI allows platforms to provide their own implementation hooks per-bar. Conventional behaviors ---------------------- [Section titled “Conventional behaviors”](https://docs.papermc.io/adventure/platform/implementing/#conventional-behaviors) Some behaviors are expected by platforms beyond what is explicitly required by implementing certain interfaces. These are: * When implementing `Audience`, any unsupported operations should fail silently. * When sending components to a player, they should be passed through `GlobalTranslator` before sending to perform any translations (note: `GlobalTranslator` is only for custom translations, and should not contain vanilla resource pack translations - they have a different interpolation syntax than `GlobalTranslator` uses) * There is no specific required list of Adventure modules to distribute with your platform, but we recommend `adventure-api`, `adventure-text-minimessage`, `adventure-text-logger-slf4j`, plus whatever serializers are required for the integration. We specifically do not recommend distributing the `adventure-text-serializer-legacy` module unless it is necessary for backwards compatibility within your platform. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Native support | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/native/#_top) Native support ============== Native platforms integrate Adventure directly with their platform’s provided API, and bundle Adventure automatically. This allows them to more tightly integrate Adventure with the rest of the game, and avoids users having to handle distributing Adventure and some platform adapter themselves. The following software provide native support for Adventure. | Platform | Minimum Version | Additional Notes | | --- | --- | --- | | Sponge | Sponge 8 (1.16.5) | | | Velocity | 1.1.0 build 158 | For more information, see the [Velocity Docs](https://docs.papermc.io/velocity/dev/pitfalls#audience-operations-are-not-fully-supported) | | Paper | 1.16.5 build 473 | | | Minestom | Build 7494725 | For more information, see the [Minestom Wiki](https://minestom.net/docs/feature/adventure) | | Fabric | `adventure-platform-fabric` 5.3.0 | This is not strictly native, but injected interfaces provide a near-native experience | Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Dynamic replacements | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#_top) Dynamic replacements ==================== MiniMessage has some included `TagResolver` s which can replace tags dynamically when parsing those. Those resolvers can replace a tag with dynamic input such as a string or a formatted number. Placeholders ------------ [Section titled “Placeholders”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#placeholders) Placeholders replace the tag with a specific text. Those are the most basic replacements: ### Insert a component [Section titled “Insert a component”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#insert-a-component) You can simply insert a component for the tag with the component placeholder. MiniMessage.miniMessage().deserialize("Hello :)", Placeholder.component("name", Component.text("TEST", NamedTextColor.RED))); This will insert the red text component “TEST” for the tag name. ### Insert some unparsed text [Section titled “Insert some unparsed text”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#insert-some-unparsed-text) Sometimes it’s better to not parse dynamic text such as user inputs. For those things MiniMessage provides the unparsed placeholder. With this method you can sanitize user input without escaping the tags directly. MiniMessage.miniMessage().deserialize("Hello ", Placeholder.unparsed("name", "TEST :)")); This will insert the text without parsing. The result will be a gray text with `Hello TEST :)`. ### Insert and parse text [Section titled “Insert and parse text”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#insert-and-parse-text) When you want to insert a text and allow MiniMessage to parse the tags you can use the parsed placeholder. The parsed placeholder will insert the replacement before parsing the string. The tags in the placeholder can affect the parsed result after the placeholder. MiniMessage.miniMessage().deserialize("Hello :)", Placeholder.parsed("name", "TEST"));// returns Component.text("Hello ", NamedTextColor.GRAY).append(Component.text("TEST :)", NamedTextColor.RED)); This will insert and parse the text. ### Insert a style [Section titled “Insert a style”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#insert-a-style) When you want to create your own styling tag you can use the styling placeholder. MiniMessage.miniMessage().deserialize("Hello :) How are you?", Placeholder.styling("my-style", ClickEvent.suggestCommand("/say hello"), NamedTextColor.RED, TextDecoration.BOLD));// will apply a click event, a red text color and bold decoration to the text This will insert the style with a click event and a red text. Styling placeholders can be used for any style, e.g. colors, text decoration and events. Create your own styling tags: Placeholder.styling("fancy", TextColor.color(150, 200, 150)); // will replace the color between "" and ""Placeholder.styling("myhover", HoverEvent.showText(Component.text("test"))); // will display your custom text as hoverPlaceholder.styling("mycmd", ClickEvent.runCommand("/mycmd is cool")); // will create a clickable text which will run your specified command. Formatters ---------- [Section titled “Formatters”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#formatters) Not everything is a text, sometimes its useful to display a number or a date. For that you can use the provided formatters from MiniMessage ### Insert a number [Section titled “Insert a number”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#insert-a-number) You can insert a `Number` by using the number formatter in MiniMessage. To specify the locale and format of the number the formatter accepts optionally tag arguments. You can specify the locale and the number format. It’s possible to pass both as arguments to the tag but you have provide the locale first. MiniMessage.miniMessage().deserialize("Hello my number !", Formatter.number("no", 250.25d));MiniMessage.miniMessage().deserialize("Hello my number !", Formatter.number("no", 250.25d));MiniMessage.miniMessage().deserialize("Hello my number !", Formatter.number("no", 250.25d));MiniMessage.miniMessage().deserialize("Hello my number !", Formatter.number("no", 250.25d)); All those examples are valid and will insert the number as the tag. Refer to Locale and DecimalFormat for valid locale tags and usable patterns. ### Insert a date [Section titled “Insert a date”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#insert-a-date) To insert an instance of an `TemporalAccessor` such as a `LocalDateTime` you can use the date formatter. The tag resolver requires a tag argument for the format. Refer to DateTimeFormatter for a usable patterns. MiniMessage.miniMessage().deserialize("Current date is: !", Formatter.date("date", LocalDateTime.now(ZoneId.systemDefault())); This will display the current date with the specified format. E.g. as `2022-05-27 11:30:25`. ### Insert a choice [Section titled “Insert a choice”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#insert-a-choice) To insert a number and format some text based on the number you can use the choice formatter. This will accept a ChoiceFormat pattern. MiniMessage.miniMessage().deserialize("I met !", Formatter.choice("choice", 5)); This will format your input based on the provided ChoiceFormat. In this case it will be `I met many developers!` Complex placeholders -------------------- [Section titled “Complex placeholders”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#complex-placeholders) You can simply create your own placeholders. Take a look at the [Formatter](https://github.com/PaperMC/adventure/blob/main/5/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java) and [Placeholder](https://github.com/PaperMC/adventure/blob/main/5/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Placeholder.java) class from MiniMessage for examples. ### Examples [Section titled “Examples”](https://docs.papermc.io/adventure/minimessage/dynamic-replacements/#examples) Create a custom tag which makes its contents clickable: TagResolver.resolver("click-by-version", (args, context) -> { final String version = args.popOr("version expected").value(); return Tag.styling(ClickEvent.openUrl("https://jd.advntr.dev/api/ " + version + "/"));});// creates a tag to get javadocs of adventure by the version: You can create your own complex placeholders with multiple arguments and their own logic. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # MiniMessage translator | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/minimessage/translator/#_top) MiniMessage translator ====================== MiniMessage provides a `Translator` implementation that allows you to use MiniMessage as translation strings. It also provides automatic support for argument placeholders, letting you use simple translatable components throughout your codebase. Creating a MiniMessage translator --------------------------------- [Section titled “Creating a MiniMessage translator”](https://docs.papermc.io/adventure/minimessage/translator/#creating-a-minimessage-translator) To start, create an implementation of the `MiniMessageTranslator` and register it to the `GlobalTranslator`. This can be done using `GlobalTranslator.translator().addSource(myMiniMessageTranslator)`. For an example of how to create your own `MiniMessageTranslator`, see the code block below. public class MyMiniMessageTranslator extends MiniMessageTranslator { public MyMiniMessageTranslator() { // By default, the standard MiniMessage instance will be used. // You can specify a custom one in the super constructor. super(MiniMessage.miniMessage()); } @Override public @Nullable String getMiniMessageString(final @NotNull String key, final @NotNull Locale locale) { // Creating a custom MiniMessage translator is as simple as overriding this one method. // All you need to do is return a MiniMessage string for the provided key and locale. // In this example we will hardcode this, but you could pull it from a resource bundle, a properties file, a config file or something else entirely. if (key.equals("mykey") && locale == Locale.US) { return "Hello, ! Today is ." } else { // Returning null "ignores" this translation. return null; } }} ### MiniMessage translation store [Section titled “MiniMessage translation store”](https://docs.papermc.io/adventure/minimessage/translator/#minimessage-translation-store) In order to make managing a `MiniMessageTranslator` easier, we also provide a `TranslationStore` implementation using MiniMessage strings. For documentation on how to use translation stores, see `localization`. Note that the `MiniMessageTranslationStore` contains the same methods as the message format translation store for populating a translation store using resource bundles. Using a MiniMessage translator ------------------------------ [Section titled “Using a MiniMessage translator”](https://docs.papermc.io/adventure/minimessage/translator/#using-a-minimessage-translator) The MiniMessage translator will automatically turn translatable component arguments into a custom tag. This tag will be `` or `` where `index` is the zero indexed position of the argument. For example, this component `Component.translatable(key, Component.text("Kezz"))` with the MiniMessage string `Hello, !` will produce “Hello, Kezz!”. You can also use the `Argument` class to create named tags for ease of use. For example, this component `Component.translatable(key, Argument.component("name", Component.text("Kezz"))` will produce the string “Hello, Kezz!” when used with either `Hello, !` or `Hello, !`. Finally, you can also add entirely custom tags or tag resolvers to the deserialization by using the rest of the methods on `Argument`. For a full list, please see the Javadocs for the `Argument` class. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # ViaVersion | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/viaversion/#_top) ViaVersion ========== On supported platforms (Sponge 7 and Bukkit), Adventure is able to enhance its functionality by using the [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) API to send packets directly to the client. This allows, for instance, for a plugin on a Minecraft 1.7 server to send RGB chat messages and titles to clients on newer versions of Minecraft. If you include the Sponge or Bukkit platforms, no further action is required: ViaVersion will be detected and support for it will be enabled. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Format | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/minimessage/format/#_top) Format ====== The MiniMessage language uses tags. Everything you do will be defined with tags. Tags have a start tag and an end tag (the `` tag is an exception here). Start tags are mandatory (obviously), but end tags aren’t outside of `strict` mode. The following are all visually identical: Hello World!Hello World!Hello World! For tags with no content, tags can be auto-closed by using the format ``. With this format, even in strict mode no separate closing tag should be provided. All tag names are case-insensitive to reduce the possibility for conflict, but we recommend keeping all tag names lowercase (or at the very least, being consistent). Some tags have argument. Those look like this: `stuff`. For example: test:TEST">TESTTEST As you can see, those sometimes contain components, sometimes just numbers, strings, or other types. Refer to the detailed docs below. Single (`'`) and double (`"`) quotes can be used interchangeably. We recommend staying consistent, though in order to minimize escaping it might make more sense to switch quote types for some arguments. Any meaningful token can be escaped in the locations where they have influence. In plain text, tag open characters (`<`) can be escaped with a leading backslash (`\`). Within quoted strings, the opening quote character can be escaped (`'` or `"`). In either place, the escape character can be escaped in places where it would otherwise be relevant. Unquoted tag arguments cannot have escapes, for simplicity. In locations where escaping is not supported, the literal escape character will be passed through. In locations where escaping _is_ supported but a literal escape character is desired, the escape character can itself be escaped to produce a `\`. The default tags try to represent components in a manner compatible with Vanilla, but simplifying some elements. It might be helpful to use [the Minecraft wiki](https://minecraft.wiki/w/Text_component_format) as a reference for the Vanilla component system, especially for things like the actions and values of click and hover events. The [MiniMessage Web Viewer](https://webui.advntr.dev/) allows testing MiniMessage text locally, without having to spin up a Minecraft instance. It can be helpful to put examples from these docs into the viewer while learning. Strict mode ----------- [Section titled “Strict mode”](https://docs.papermc.io/adventure/minimessage/format/#strict-mode) By default, MiniMessage is extremely lenient, and any invalid tags will just be ignored. Any tags left unclosed at the end of an input string will be automatically closed. Applications can optionally enable _strict mode_, which prohibits using ``, and requires all tags to be closed in reverse order of opening. Any application using MiniMessage should make it clear to end users which language variant is being used. Standard tags ------------- [Section titled “Standard tags”](https://docs.papermc.io/adventure/minimessage/format/#standard-tags) These are the tags included and enabled by default in MiniMessage. Specific parsers of MiniMessage may add custom tags to this list, or restrict the available tags to a subset of this list. Consult application documentation for details. ### Color [Section titled “Color”](https://docs.papermc.io/adventure/minimessage/format/#color) Color the next parts Tag * `<_colorname_>` Arguments * `_colorname_`, any minecraft color constant: `black`, `dark_blue`, `dark_green`, `dark_aqua`, `dark_red`, `dark_purple`, `gold`, `gray`, `dark_gray`, `blue`, `green`, `aqua`, `red`, `light_purple`, `yellow`, or `white`. `dark_grey` can be used in place of `dark_gray`, and so can `grey` in place of `gray`. Hex colors are supported as well, with the format `#RRGGBB`. Examples Hello World!This is a test!<#00ff00>R G B! ![The result of parsing `Hello World!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/color_1.IcvdrsE-_Z154k18.webp) ![The result of parsing `This is a test!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/color_2.lNFDCgYx_ZCKxAL.webp) ### Color (verbose) [Section titled “Color (verbose)”](https://docs.papermc.io/adventure/minimessage/format/#color-verbose) A more verbose way of defining colors Tag * `` Aliases * `colour`, `c` Arguments * `_colorNameOrHex_`, can be any of the values from above (so named colors or hex colors) Examples Hello World!This is a test! ![The result of parsing `Hello World!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/color_1.IcvdrsE-_Z154k18.webp) ![The result of parsing `This is a test!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/color_2.lNFDCgYx_ZCKxAL.webp) ### Shadow Color [Section titled “Shadow Color”](https://docs.papermc.io/adventure/minimessage/format/#shadow-color) Color the shadow of the next parts Tag * `` * `` as an alias to disable the shadow (equivalent to ``) Arguments * `_colorNameOrHex_`, a named color or hex color string with the format `#RRGGBB` or `#RRGGBBAA` * `[alpha_as_float]`, a float value between 0 and 1, representing the alpha value of the shadow. Optional, defaults to 0.25. Has no effect if an alpha value is already provided in the hex color string. Examples Hello World!This is a test!Thicc ![The result of parsing `Hello World!` shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/shadow_1.BKCci3At_Z2ws1h3.webp) ![The result of parsing `This is a test!` shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/shadow_2.kx89mZsr_Pgnmu.webp) ![The result of parsing `Thicc` shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/shadow_3.DB_UDhhl_XgLUJ.webp) ### Decoration [Section titled “Decoration”](https://docs.papermc.io/adventure/minimessage/format/#decoration) Decorate the next parts Tag * `<_decorationname_[:false]>`, or `` as an alias to invert the decoration. Arguments * `_decorationname_`, Any decoration supported in Minecraft: | Decoration | Aliases | | --- | --- | | `bold` | `b` | | `italic` | `em` or `i` | | `underlined` | `u` | | `strikethrough` | `st` | | `obfuscated` | `obf` | Examples This is important! ![The result of parsing `This is important!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/decoration_1.YHM0gk3g_ZmtT1Y.webp) ### Reset [Section titled “Reset”](https://docs.papermc.io/adventure/minimessage/format/#reset) Close all currently open tags, resetting color/decoration/etc. The reset tag cannot be closed. In strict mode, reset tags are forbidden. Tag * `` Arguments * none Examples Hello world! ![The result of parsing `Hello world!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/reset_1.CaE1z_qU_Z3fsWt.webp) ### Click [Section titled “Click”](https://docs.papermc.io/adventure/minimessage/format/#click) Allows doing multiple things when clicking on the component. Tag * `` Arguments * `_action_`, the type of click event, one of [this list](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/event/ClickEvent.Action.html#enum.constant.summary) * `_value_`, the argument for that particular event, refer to [the minecraft wiki](https://minecraft.wiki/w/Text_component_format) Examples Click to show the world seed!Click this to copy your score! ![The result of parsing `Click to show the world seed!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/click_1.Dlx2nqaC_ZHmyva.webp) ### Hover [Section titled “Hover”](https://docs.papermc.io/adventure/minimessage/format/#hover) Allows doing multiple things when hovering on the component. Tag * `` Arguments * `_action_`, the type of hover event, one of this [list](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/event/HoverEvent.Action.html#field.summary) * `_value_`, argument(s) specific to each event action: | Action | Value | Description | | --- | --- | --- | | `show_text` | `_text_` | a MiniMessage string | | `show_item` | `_type_[:_count_[(:_componentKey_:_componentValue_)...]]` | a `Key` for the item’s type, optionally followed by count (an integer) and a list of [data component](https://minecraft.wiki/w/Data_component_format)
key value pairs | | Legacy `_type_[:_count_[:tag]]` | a `Key` for the item’s type, optionally followed by count (an integer) and tag (a [SNBT](https://minecraft.wiki/w/NBT_format#SNBT_format)
string) | | `show_entity` | `_type_:_uuid_[:_name_]` | a `Key` ID of the entity type, the entity’s UUID, and an optional custom name | Examples test'>TEST ![The result of parsing `test'>TEST`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/hover_1.D4vGWpwW_18IDp2.webp) Very sharp sword! ![Very sharp sword!](https://docs.papermc.io/_astro/hover_2.D7JVIy0B_eGFo8.webp) ### Keybind [Section titled “Keybind”](https://docs.papermc.io/adventure/minimessage/format/#keybind) Allows displaying the configured key for actions Tag * `` Arguments * `_key_`, the keybind identifier of the action Examples Press to jump! ![The result of parsing `Press to jump!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/key_1.CJD6vo1W_1TxJNp.webp) ### Translatable [Section titled “Translatable”](https://docs.papermc.io/adventure/minimessage/format/#translatable) Allows displaying minecraft messages using the player locale Tag * `` Aliases * `tr`, `translate` Arguments * `_key_`, the translation key * `_valueX_`, optional values that are used for placeholders in the key (they will end up in the `with` tag in the JSON) Examples You should get a !1':'Stone'>! ![The result of parsing `You should get a !`, shown in-game in the Minecraft client's chat window in English](https://docs.papermc.io/_astro/translatable_1.DfyS0jwu_Z23skiJ.webp) ![The result of parsing `1':'Stone'>!`, shown in-game in the Minecraft client's chat window in English](https://docs.papermc.io/_astro/translatable_2.x3w4Igoy_1tcsR0.webp) ### Fallback [Section titled “Fallback”](https://docs.papermc.io/adventure/minimessage/format/#fallback) Allows displaying minecraft messages using the player locale, or a fallback if no text is available Tag * `` Aliases * `tr_or`, `translate_or` Arguments * `_key_`, the translation key * `_fallback_`, the fallback text to display * `_valueX_`, optional values that are used for placeholders in the key (they will end up in the `with` tag in the JSON) Examples You should get a ! ### Insertion [Section titled “Insertion”](https://docs.papermc.io/adventure/minimessage/format/#insertion) Allow insertion of text into chat via shift click Tag * `` Arguments * `_text_`, the text to insert Examples Shift-click this to insert! ![The result of parsing `Shift-click this to insert!`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/insertion_1.BQGGa26X_Z1BUmNF.webp) ### Rainbow [Section titled “Rainbow”](https://docs.papermc.io/adventure/minimessage/format/#rainbow) Rainbow-colored text?! Tag * `` Arguments * phase, optional * `!`, literal value which reverses the rainbow, optional Examples Woo: ||||||||||||||||||||||||!Woo: ||||||||||||||||||||||||!Woo: ||||||||||||||||||||||||!Woo: ||||||||||||||||||||||||! ![The result of parsing all four examples in series, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/rainbow_1.BiomJch9_ZyhpNd.webp) ### Gradient [Section titled “Gradient”](https://docs.papermc.io/adventure/minimessage/format/#gradient) Gradient colored text Tag * `` Arguments * a list of 1 to n colors, either hex or named colors and an optional phase parameter (range -1 to 1) allows you to shift the gradient around, creating animations. Examples Woo: ||||||||||||||||||||||||!Woo: ||||||||||||||||||||||||!Woo: ||||||||||||||||||||||||!Woo: ||||||||||||||||||||||||! ![The result of parsing the examples for the gradient tag, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/gradient_1.BJ83LXbF_ZAwHrU.webp) ### Transition [Section titled “Transition”](https://docs.papermc.io/adventure/minimessage/format/#transition) Transitions between colors. Similar to a gradient, but everything is the same color and the phase chooses that color Tag * `` Arguments * a list of 1 to n colors, either hex or named colors and an optional phase parameter (range -1 to 1) allows you to shift the transition around, creating animations. Examples |||||||||Hello world [phase] ![The result of parsing `Hello World [phase]`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/transition_1.C8s6W3Vr_ZEVGEP.webp) ### Font [Section titled “Font”](https://docs.papermc.io/adventure/minimessage/format/#font) Allows to change the font of the text Tag * `` Arguments * the namespaced key of the font, defaulting to `minecraft` Examples Nothing Uniform Alt UniformUses a custom font from a resource pack ![The result of parsing `Nothing Uniform Alt Uniform`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/font_1.C16TEtLm_ZfGeBs.webp) ### Newline [Section titled “Newline”](https://docs.papermc.io/adventure/minimessage/format/#newline) Insert a newline character. Tag * `` Aliases * `br` Arguments * none Examples Let me insert a line break here.Hover with aline break'>Text withline break ![The result of parsing `Hover with aline break'>Text withline break`, shown in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/newline_1.DYHjw1ME_Vtyky.webp) ### Selector [Section titled “Selector”](https://docs.papermc.io/adventure/minimessage/format/#selector) _(since v4.11.0)_ Insert a selector component Tag * `` Aliases * `sel` Arguments * `_sel_`, the selector pattern to insert * `_separator_` (optional), the separator to insert between values the selector matches Examples Hello , I'm ! ![The result of parsing `Hello , I'm !`, show in-game in the Minecraft client's chat window](https://docs.papermc.io/_astro/selector_1.B99vc1oz_Z1cHlsK.webp) ### Score [Section titled “Score”](https://docs.papermc.io/adventure/minimessage/format/#score) _(since v4.13.0)_ Insert a score component. Tag * `` Arguments: * `_name_`, the name of the score holder on the server scoreboard, or a selector resolved with receiver context * `_objective_`, the name of the objective to get `name`’s score in Examples You have won games! ### NBT [Section titled “NBT”](https://docs.papermc.io/adventure/minimessage/format/#nbt) _(since v4.13.0)_ Insert a NBT component. The syntax of this tag is intended to be familiar to users of vanilla Minecraft’s `/data` command. Tag * `` Aliases * `data` Arguments: * `block|entity|storage` the type of data source to read from — a `block` entity, an `entity` selector, or the persistent command `storage` container * `_id_`, the position for a block NBT component, a selector for an entity NBT component, or a key (resource location) for a storage NBT component * `_path_`, the NBT path to resolve from within the data source * `_separator_`, the separator between multiple values, if (primarily for entity NBT) the data source returns more than one * `interpret`, the literal text `interpret` if the result should be parsed as component JSON Examples Your health is ### Pride [Section titled “Pride”](https://docs.papermc.io/adventure/minimessage/format/#pride) _(since v4.18.0)_ Colors the text inside the tags with a gradient corresponding to a pride flag. Tag * `` Arguments * `flag` the flag to use, may be one of pride, progress, trans, bi, pan, nb, lesbian, ace, agender, demisexual, genderqueer, genderfluid, intersex, aro, baker, philly, queer, gay, bigender, demigender, femboy or intersex inclusive. * `phase` phase, a number between -1 and 1, optional Examples Happy pride month!Kyori supports trans rights! ### Sprite [Section titled “Sprite”](https://docs.papermc.io/adventure/minimessage/format/#sprite) _(since v4.25.0)_ Inserts a sprite. Tag * `` Arguments * `atlas` the atlas to use, e.g. `minecraft:blocks`. * `sprite` the sprite to use, e.g. `item/emerald`. Examples Look at my !This item costs 10 x . ### Head [Section titled “Head”](https://docs.papermc.io/adventure/minimessage/format/#head) _(since v4.25.0)_ Inserts a player head. Tag * `` Arguments * `name|uuid|texture` the name, UUID or path to the texture of the skin to use to draw the head. * `outer_layer` either `true` or `false`, determines if the outer layer (or “hat” layer) should be drawn. Defaults to `true`. Examples My favorite dev is .Do you prefer Steve or Alex?Thanks for the docs! Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # MiniMessage API | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/minimessage/api/#_top) MiniMessage API =============== Dependency ---------- [Section titled “Dependency”](https://docs.papermc.io/adventure/minimessage/api/#dependency) Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/minimessage/api/#tab-panel-6) * [Gradle (Groovy)](https://docs.papermc.io/adventure/minimessage/api/#tab-panel-7) * [Maven](https://docs.papermc.io/adventure/minimessage/api/#tab-panel-8) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-text-minimessage:5.2.0")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-text-minimessage:5.2.0'} net.kyori adventure-text-minimessage 5.2.0 Getting started --------------- [Section titled “Getting started”](https://docs.papermc.io/adventure/minimessage/api/#getting-started) MiniMessage exposes a simple API via the `MiniMessage` class. A standard instance of the serializer is available through the `miniMessage()` method. This uses the default set of tags and is not in strict mode. Additional customization of MiniMessage is possible via the [Builder](https://docs.papermc.io/adventure/minimessage/api/#builder) . MiniMessage allows you to both serialize components into MiniMessage strings and to parse/deserialize MiniMessage strings into components. Here’s a short example to try things out: Audience player = ...;MiniMessage mm = MiniMessage.miniMessage(); Component parsed = mm.deserialize("Hello world, isn't MiniMessage fun?"); player.sendMessage(parsed); For more advanced uses, additional tag resolvers can be registered, which when given a tag name and arguments will produce a `Tag` instance. These are described in more detail below. ### Presets [Section titled “Presets”](https://docs.papermc.io/adventure/minimessage/api/#presets) MiniMessage also provides a set of presets that can be used instead of the main MiniMessage instance. These presets are intended to easily allow developers to avoid accidentally allowing users to use abusable component features, such as the run command click event. Below is a list of available presets and their functionality: * **`DEFAULT`** The default preset, containing all MiniMessage features. This is the same as `MiniMessage.miniMessage()`. * **`NON_INTERACTABLE`** A preset that disables all component features that allow for interaction. This includes click events, hover events, and text insertion. It also includes a custom post-processor that removes any interactable elements from the resulting component. Therefore, this can also be used with custom tag resolvers that may produce interactable components. * **`FORMATTED_TEXT`** A preset that only allows text components and associated formatting. This includes coloring, shadow, font, and text decoration (e.g., bold, italics). It also includes a custom post-processor that removes any non-text components or interactable elements from the resulting component. Therefore, this can also be used with custom tag resolvers. // You can get a pre-built MiniMessage instance based on any preset.final MiniMessage miniMessage = MiniMessage.miniMessage(MiniMessage.Preset.NON_INTERACTABLE); // Alternatively, you can get a pre-configured builder...final MiniMessage.Builder builder = MiniMessage.builder(MiniMessage.Preset.NON_INTERACTABLE); // ...then add your own tags or override other settings if needed...builder.editTags(tags -> { tags .resolver(new MyCustomTagResolver()) .resolver(fetchExternalTags());}); // ...and finally, build your MiniMessage instance!final MiniMessage myCustomMiniMessageInstance = builder.build(); ### Builder [Section titled “Builder”](https://docs.papermc.io/adventure/minimessage/api/#builder) To make customizing MiniMessage easier, we provide a Builder. The specific methods on the builder are explained in the javadoc. MiniMessage minimessage = MiniMessage.builder() .tags(TagResolver.builder() .resolver(StandardTags.color()) .resolver(StandardTags.decorations()) .resolver(this.someResolvers) .build() ) .build(); ### Error handling [Section titled “Error handling”](https://docs.papermc.io/adventure/minimessage/api/#error-handling) By default, MiniMessage will never throw an exception caused by user input. Instead, it will treat any invalid tags as normal text. `MiniMessage.Builder#strict(true)` mode will enable strict mode, which throws exceptions on unclosed tags, but still will allow any improperly specified tags through. To capture information on why a parse may have failed, `MiniMessage.Builder#debug(Consumer)` can be provided, which will accept debug logging for an input string. Tag resolvers ------------- [Section titled “Tag resolvers”](https://docs.papermc.io/adventure/minimessage/api/#tag-resolvers) All tag resolution goes through tag resolvers. There is one global tag resolver, which describes the tags available through a `MiniMessage` instance, plus parse-specific resolvers which can provide additional input-specific tags. Tag resolvers are the binding between a name and arguments, and the logic to produce a `Component` contained in a `Tag` instance. They are composable so a `TagResolver` can produce any number of actual `Tag` instances. The tag name passed to resolvers will always be lower-cased, to ensure case-insensitive searches. Tag names are only allowed to contain the characters a-z, 0-9, `_`, and `-`. They can also optionally start with any of the following characters: `!?#`. You can create your own `TagResolver` by using the static factory methods in `TagResolver`. To replace tags dynamically with text MiniMessage has built-in `Placeholder` and `Formatter`. Where possible, these built-in resolvers should be used, as MiniMessage can flatten combinations of these resolvers into a more efficient format. For built-in dynamic replacements take a look [here](https://docs.papermc.io/adventure/minimessage/dynamic-replacements) . To combine multiple resolvers, take a look at the tag resolver builder, `TagResolver.builder()`. The builder for `MiniMessage` allows providing a custom tag resolver rather than the default (`StandardTags.all()`), allowing MiniMessage also provides convenience methods to do that: MiniMessage serializer = MiniMessage.builder() .tags(TagResolver.builder() .resolver(StandardTags.color()) .build() ) .build(); Component parsed = serializer.deserialize("Hai"); // Assertion passesassertEquals(Component.text("Hai", NamedTextColor.GREEN), parsed); Because the `` tag is not enabled on this builder, the bold tag is interpreted as literal text. ### Handling arguments [Section titled “Handling arguments”](https://docs.papermc.io/adventure/minimessage/api/#handling-arguments) Tag resolvers have an `ArgumentQueue` parameter, which provides any tag arguments that are present in the input. Helper methods on `Tag.Argument` can assist with conversions of the tag. Exceptions thrown by the `popOr()` methods will interrupt execution, but are not currently exposed to users outside of debug output. We plan to add an auto-completion function that can reveal some of this information to the user, so please do try to write useful error messages in custom tag resolvers. Tags ---- [Section titled “Tags”](https://docs.papermc.io/adventure/minimessage/api/#tags) Once a tag resolver has handled arguments, it returns a `Tag` object. These objects implement the logic of producing or modifying a component tree. There are three main kinds of `Tag` — all custom implementations must implement one of these interfaces. ### Pre-process [Section titled “Pre-process”](https://docs.papermc.io/adventure/minimessage/api/#pre-process) These tags implement the `PreProcess` interface, and have a value of a raw MiniMessage string that is replaced into the user input before parsing continues. Due to limitations in the current parser implementation, note that pre-process tags will adjust offsets in error messages, and may inhibit tab completion. However, they are currently the only way to integrate markup fragments into a message. ### Inserting [Section titled “Inserting”](https://docs.papermc.io/adventure/minimessage/api/#inserting) These tags are fairly straightforward: they represent a literal `Component`. The vast majority of Tag implementations will want to be `Inserting` tags. `Inserting` tags may also optionally be self-closing — by default, this is only true for tags created by `Placeholder.unparsed(String)` and `Placeholder.component(Component)`, so that placeholders are self-contained. Most `standard tags <./format>` are `Inserting`. These tags will either directly insert a component, or use the helper `Tag.styling(StyleBuilderApplicable...)` to apply style to components. This helper can be used to efficiently apply a collection of styles with one tag. For example, to create a `Title` tag, that makes the `Title` text into a link that opens a URL with traditional link styling, this could be used: Component aTagExample() { final String input = "Hello, click me! but not me!"; final MiniMessage extendedInstance = MiniMessage.builder() .editTags(b -> b.tag("a", MiniMessageTest::createA)) .build(); return extendedInstance.deserialize(input);} static Tag createA(final ArgumentQueue args, final Context ctx) { final String link = args.popOr("The tag requires exactly one argument, the link to open").value(); return Tag.styling( NamedTextColor.BLUE, TextDecoration.UNDERLINED, ClickEvent.openUrl(link), HoverEvent.showText(Component.text("Open " + link)) );} This allows producing rich styling relatively quickly. ### Modifying [Section titled “Modifying”](https://docs.papermc.io/adventure/minimessage/api/#modifying) Modifying tags are the most complex, and most specialized of the tag types available. These tags receive the node tree and have an opportunity to analyze it before components are constructed, and then receive every produced child component and can modify those children. This is used for the built-in `` and `` tags, but can be applied for similar complex transformations. Modifying tags are first given an opportunity to visit every node of the tree in a depth-first traversal. If a `Modifying` instance stores any state during this traversal, its resolver should return a new instance every time to prevent state corruption. Once the whole parse tree has been visited, the `postVisit()` method is called. This method can optionally be overridden if any additional calculations must be performed. Next, the `Modifying` instance enters the application phase, where the component tree is presented to the tag for transformation. This allows the tag to _modify_ the contents of these components, giving it its name. ### Parser directives [Section titled “Parser directives”](https://docs.papermc.io/adventure/minimessage/api/#parser-directives) Parser directives are a special kind of tag, as they are instructions for the parser, and therefore cannot be implemented by end users. There is currently only one, but more may be added at any time. | Directive | Description | | --- | --- | | RESET | This indicates to the parser that this tag should close all currently open tags. | This can be used to provide the functionality of a `` tag under a different name. For example: final var clearTag = TagResolver.resolver("clear", ParserDirective.RESET); final var parser = MiniMessage.builder() .editTags(t -> t.resolver(clearTag)) .build(); final Component parsed = parser.deserialize("hello world, how are you?"); This code would add a `` tag, behaving identically to the `` tag available by default — ”, how are you?” would not be bold or colored red. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Bukkit | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/bukkit/#_top) Bukkit ====== The Adventure platform implementation for Bukkit targets Paper, Spigot, and Bukkit for Minecraft 1.7.10 through 1.21.11. Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/platform/bukkit/#tab-panel-9) * [Gradle (Groovy)](https://docs.papermc.io/adventure/platform/bukkit/#tab-panel-10) * [Maven](https://docs.papermc.io/adventure/platform/bukkit/#tab-panel-11) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-platform-bukkit:4.4.1")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-platform-bukkit:4.4.1'} net.kyori adventure-platform-bukkit 4.4.1 Usage ----- [Section titled “Usage”](https://docs.papermc.io/adventure/platform/bukkit/#usage) You should first obtain a `BukkitAudiences` object by using `BukkitAudiences.create(plugin)`. This object is thread-safe and can be reused from different threads if needed. From here, Bukkit `CommandSender`s and `Player`s may be converted into `Audience`s using the appropriate methods on `BukkitAudiences`. The audiences object should also be closed when a plugin is disabled in order to clean up resources and increase the likelihood of a successful `/reload`. public class MyPlugin extends JavaPlugin { private BukkitAudiences adventure; @NonNull public BukkitAudiences adventure() { if (this.adventure == null) { throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!"); } return this.adventure; } @Override public void onEnable() { // Initialize an audiences instance for the plugin this.adventure = BukkitAudiences.create(this); // then do any other initialization } @Override public void onDisable() { if (this.adventure != null) { this.adventure.close(); this.adventure = null; } }} This audience provider should be used over the serializers directly, since it will handle compatibility measures for sending messages across versions. Component serializers --------------------- [Section titled “Component serializers”](https://docs.papermc.io/adventure/platform/bukkit/#component-serializers) For areas that aren’t covered by the `Audience` interface, the Bukkit platform provides the `MinecraftComponentSerializer` (available on CraftBukkit-based servers), and the `BungeeComponentSerializer` (available on Spigot and Paper servers) to convert directly between Adventure [Components](https://docs.papermc.io/adventure/text) and other component types. For uses that don’t integrate directly with native types, JSON and legacy format serializers for the running server version are exposed in `BukkitComponentSerializer`. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Version history | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/version-history/#_top) Version history =============== These changelogs for individual projects mirror those posted on the GitHub Releases page of each project’s repository. [adventure](https://docs.papermc.io/adventure/version-history/adventure) [adventure-platform](https://docs.papermc.io/adventure/version-history/adventure-platform) [adventure-platform-mod](https://docs.papermc.io/adventure/version-history/adventure-platform-mod) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Resource packs | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/resource-pack/#_top) Resource packs ============== On top of the resource packs controlled by each player on their client, the game allows servers to send resource pack URLs to clients that the players can choose to accept. This allows servers to provide customized styling. Initially this just allowed sending a single resource pack, but starting with _Minecraft 1.20.3_ the server can send multiple resource packs to be stacked, and if needed removed individually. Sending resource packs ---------------------- [Section titled “Sending resource packs”](https://docs.papermc.io/adventure/resource-pack/#sending-resource-packs) A resource pack is identified by: * its UUID * a URI to the resource pack ZIP file * the SHA-1 hash of the resource pack ZIP file as a hex string This is referred to as `ResourcePackInfo`. For every batch of resource packs being sent, a `ResourcePackRequest`, there is: * one or more resource packs * a callback to perform actions based on the responses from the client * a toggle for whether to replace any existing server-provided resource packs, or stack the most recent packs on top * whether these resource packs are required * a prompt to display to the user if they have not yet chosen whether to allow server resource packs Examples -------- [Section titled “Examples”](https://docs.papermc.io/adventure/resource-pack/#examples) Send a single resource pack to a client that is required, with a UUID computed based on its name. private static final ResourcePackInfo PACK_INFO = ResourcePackInfo.resourcePackInfo() .uri(URI.create("https://example.com/resourcepack.zip")) .hash("2849ace6aa689a8c610907a41c03537310949294") .build(); public void sendResourcePack(final @NonNull Audience target) { final ResourcePackRequest request = ResourcePackRequest.resourcePackRequest() .packs(PACK_INFO) .prompt(Component.text("Please download the resource pack!")) .required(true) .build(); // Send the resource pack request to the target audience target.sendResourcePacks(request);} public void sendOptionalResourcePack(final @NonNull Audience target) { final ResourcePackRequest request = ResourcePackRequest.resourcePackRequest() .packs(PACK_INFO) .prompt(Component.text("Please download the resource pack!")) .required(false) .build(); // Send the resource pack request to the target audience target.sendResourcePacks(request);} Callbacks --------- [Section titled “Callbacks”](https://docs.papermc.io/adventure/resource-pack/#callbacks) The callback function allows servers to respond to pack download feedback sent by the client. Newer versions of the game provide more information about different phases, but any version will provide basic status info about download and application. Keep in mind that the responses are entirely driven by the client, so modded clients may send incorrect information (for example, saying a required resource pack has been applied when it has not), none at all, or even nonsensical information (status updates after a terminal update has been received). Any action taken based on a callback should therefore be defensively designed to cope with client creativity. The audience provided in the callback aims to be the exact same audience the resource pack was sent to in the case of wrapping audiences, re-wrapping any underlying returned value where necessary. Removing resource packs ----------------------- [Section titled “Removing resource packs”](https://docs.papermc.io/adventure/resource-pack/#removing-resource-packs) Resource packs can be removed, either some quantity at a time with `Audience.removeResourcePacks()`, or all at once with `Audience.clearResourcePacks()`. The removal methods have multiple overloads, allowing removal by a bare UUID, or by reusing the data structures used for applying resource packs. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # BungeeCord | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/bungeecord/#_top) BungeeCord ========== Adventure targets the latest version of BungeeCord and BungeeCord-compatible forks, such as Waterfall. Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/platform/bungeecord/#tab-panel-12) * [Gradle (Groovy)](https://docs.papermc.io/adventure/platform/bungeecord/#tab-panel-13) * [Maven](https://docs.papermc.io/adventure/platform/bungeecord/#tab-panel-14) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-platform-bungeecord:4.4.1")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-platform-bungeecord:4.4.1'} net.kyori adventure-platform-bungeecord 4.4.1 Usage ----- [Section titled “Usage”](https://docs.papermc.io/adventure/platform/bungeecord/#usage) You should first obtain a `BungeeAudiences` object by using `BungeeAudiences.create(plugin)`. This object is thread-safe and can be reused from different threads if needed. This object should also be _closed_ when the plugin is disabled. Note that not all functionality is available on the proxy. Sending chat messages, action bar messages, titles, and boss bars, and tab list header and footer are supported, but all other requests will fail silently. A simple example of how to appropriately initialize this platform follows: public class MyPlugin extends Plugin { private BungeeAudiences adventure; @NonNull public BungeeAudiences adventure() { if (this.adventure == null) { throw new IllegalStateException("Cannot retrieve audience provider while plugin is not enabled"); } return this.adventure; } @Override public void onEnable() { this.adventure = BungeeAudiences.create(this); } @Override public void onDisable() { if (this.adventure != null) { this.adventure.close(); this.adventure = null; } }} Component serializers --------------------- [Section titled “Component serializers”](https://docs.papermc.io/adventure/platform/bungeecord/#component-serializers) For functionality not already supported by `Audience`, the `BungeeComponentSerializer` allows you to convert between Adventure [Components](https://docs.papermc.io/adventure/text) and the native BungeeCord chat component API and back. For some areas of the proxy (notably, sending server list responses), the component serializer cannot be appropriately injected unless a `BungeeAudiences` instance has been initialized. Using Adventure `Component` instances **will not** work without a created `BungeeAudiences` instance. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # adventure-platform-mod | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#_top) adventure-platform-mod ====================== 🌍 adventure-platform-mod 7.0.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 7.0.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v7.0.0) Released on Jun 17, 2026 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v7.0.0) This version of adventure-platform-mod adds support for Minecraft 26.2, distributing Adventure 5.1.1 for the Fabric and NeoForge platforms. Minecraft versions older than 26.2 are not supported by this release. What's Changed -------------- ### Other * Remove platform-api dependency, update links/docs by [@kezz](https://github.com/kezz) in [#254](https://github.com/PaperMC/adventure-platform-mod/pull/254) * Update to Adventure 5 by [@jpenilla](https://github.com/jpenilla) in [#258](https://github.com/PaperMC/adventure-platform-mod/pull/258) New Contributors ---------------- * [@kezz](https://github.com/kezz) made their first contribution in [#254](https://github.com/PaperMC/adventure-platform-mod/pull/254) **Full Changelog**: [v6.9.0...v7.0.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.9.0...v7.0.0) * * * 🌍 adventure-platform-mod 6.9.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.9.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.9.0) Released on Apr 15, 2026 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.9.0) This version of adventure-platform-mod adds support for Minecraft 26.1 through 26.1.2, distributing Adventure 4.26.1 for the Fabric and NeoForge platforms. Minecraft versions older than 26.1 are not supported by this release. **Full Changelog**: [v6.8.0...v6.9.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.8.0...v6.9.0) * * * 🌍 adventure-platform-mod 6.8.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.8.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.8.0) Released on Dec 9, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.8.0) This version of adventure-platform-mod adds support for Minecraft 1.21.11, distributing Adventure 4.25.0 for the Fabric and NeoForge platforms. Minecraft versions older than 1.21.11 are not supported by this release. **Full Changelog**: [v6.7.0...v6.8.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.7.0...v6.8.0) * * * 🌍 adventure-platform-mod 6.7.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.7.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.7.0) Released on Oct 6, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.7.0) This version of adventure-platform-mod adds support for Minecraft 1.21.9, distributing Adventure 4.25.0 for the Fabric and NeoForge platforms. Minecraft versions older than 1.21.9 are not supported by this release. **Full Changelog**: [v6.6.0...v6.7.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.6.0...v6.7.0) * * * 🌍 adventure-platform-mod 6.6.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.6.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.6.0) Released on Jul 30, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.6.0) This version of adventure-platform-mod updates the distributed version of Adventure to 4.24.0. **Full Changelog**: [v6.5.1...v6.6.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.5.1...v6.6.0) * * * 🌍 adventure-platform-mod 6.5.1 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.5.1”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.5.1) Released on Jul 23, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.5.1) This version of adventure-platform-mod is a hotfix to address metadata not passing Maven Central validation. **Full Changelog**: [v6.5.0...v6.5.1](https://github.com/PaperMC/adventure-platform-mod/compare/v6.5.0...v6.5.1) * * * 🌍 adventure-platform-mod 6.5.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.5.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.5.0) Released on Jul 23, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.5.0) This version of adventure-platform-mod adds support for Minecraft 1.21.6 through 1.21.8, distributing Adventure 4.23.0 for the Fabric and NeoForge platforms. Minecraft versions older than 1.21.6 are not supported by this release. What's Changed -------------- ### ✨ Features * Minecraft 1.21.6 by [@jpenilla](https://github.com/jpenilla) in [#206](https://github.com/PaperMC/adventure-platform-mod/pull/206) **Full Changelog**: [v6.4.0...v6.5.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.4.0...v6.5.0) * * * 🌍 adventure-platform-mod 6.4.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.4.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.4.0) Released on May 10, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.4.0) This version of adventure-platform-mod adds support for Minecraft 1.21.5, distributing Adventure 4.21.0 for the Fabric and NeoForge platforms. What's Changed -------------- * Initial update for Minecraft 1.21.5 by [@jpenilla](https://github.com/jpenilla) in [#197](https://github.com/PaperMC/adventure-platform-mod/pull/197) **Full Changelog**: [v6.3.0...v6.4.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.3.0...v6.4.0) * * * 🌍 adventure-platform-mod 6.3.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.3.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.3.0) Released on Apr 5, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.3.0) This release of adventure-platform-mod packages adventure 4.20.0 supporting Minecraft 1.21.4 for the Fabric and NeoForge platforms. The only change in this release is to bump the packaged versions of Adventure and its dependencies. **Full Changelog**: [v6.2.0...v6.3.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.2.0...v6.3.0) * * * 🌍 adventure-platform-mod 6.2.0 ------------------------------- [Section titled “🌍 adventure-platform-mod 6.2.0”](https://docs.papermc.io/adventure/version-history/adventure-platform-mod/#v6.2.0) Released on Dec 23, 2024 - [GitHub](https://github.com/PaperMC/adventure-platform-mod/releases/tag/v6.2.0) This feature release of adventure-platform-mod bundles Adventure 4.18.0, compatible with Minecraft 1.21.2-1.21.4 on the Fabric and NeoForge platforms. What's Changed -------------- ### 🐛 Fixes * Add dependencies to fabric-repack by [@jpenilla](https://github.com/jpenilla) in [#172](https://github.com/PaperMC/adventure-platform-mod/pull/172) * fix(common): Add DCV converter for MM -> Gson by [@zml2008](https://github.com/zml2008) in [#178](https://github.com/PaperMC/adventure-platform-mod/pull/178) ### Other * build: Replace hacky workarounds for run configs by [@jpenilla](https://github.com/jpenilla) in [#173](https://github.com/PaperMC/adventure-platform-mod/pull/173) **Full Changelog**: [v6.1.0...v6.2.0](https://github.com/PaperMC/adventure-platform-mod/compare/v6.1.0...v6.2.0) * * * Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # SpongeAPI | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/spongeapi/#_top) SpongeAPI ========= Adventure provides a platform for SpongeAPI 7 for _Minecraft: Java Edition_ 1.12. Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/platform/spongeapi/#tab-panel-21) * [Gradle (Groovy)](https://docs.papermc.io/adventure/platform/spongeapi/#tab-panel-22) * [Maven](https://docs.papermc.io/adventure/platform/spongeapi/#tab-panel-23) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-platform-spongeapi:4.4.1")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-platform-spongeapi:4.4.1'} net.kyori adventure-platform-spongeapi 4.4.1 Usage ----- [Section titled “Usage”](https://docs.papermc.io/adventure/platform/spongeapi/#usage) The SpongeAPI platform can either be created through Guice dependency injection, or created directly. We recommend using injection, since less boilerplate is required. An example plugin is fairly straightforward: @Plugin(/* [...] */)public class MyPlugin { private final SpongeAudiences adventure; @Inject MyPlugin(final SpongeAudiences adventure) { this.adventure = adventure; } @NonNull public SpongeAudiences adventure() { return this.adventure; }} This sets up a `SpongeAudiences` instance that can provide audiences for players, or any `MessageReceiver`. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # ANSI | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/serializer/ansi/#_top) ANSI ==== The ANSI text serializer is an encoder that converts components to text containing [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) , which allows for styled text in a terminal. This can then be used to, for example, output server logs containing components while preserving their color and style. Note that since it’s an encoder, it can only serialize components, and can’t deserialize text back into components. Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/serializer/ansi/#tab-panel-24) * [Gradle (Groovy)](https://docs.papermc.io/adventure/serializer/ansi/#tab-panel-25) * [Maven](https://docs.papermc.io/adventure/serializer/ansi/#tab-panel-26) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-text-serializer-ansi:5.2.0")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-text-serializer-ansi:5.2.0'} net.kyori adventure-text-serializer-ansi 5.2.0 Usage ----- [Section titled “Usage”](https://docs.papermc.io/adventure/serializer/ansi/#usage) Different kind of ANSI escape codes exist, allowing for different levels of color precision, however, not all terminals support newer kinds of ANSI escape sequences. By default, `ANSIComponentSerializer` will attempt to guess the supported kinds of escape sequences based on the system’s environment variables. This can be overridden individually for a single serializer instance using the `colorLevel` method of the builder. It can also be overridden globally using system properties, using the property `net.kyori.ansi.colorLevel`, which can be set when launching the JVM using the command-line option `-Dnet.kyori.ansi.colorLevel=value`. 4 different values can be set: * `none`: Prevent any ANSI escape sequences from being emitted at all. * `indexed16`: The original set of 16 colors. * `indexed256`: Slightly newer set of 256 colors. * `truecolor`: Full 24-bit spectrum of colors. ANSI escape sequences can also be disabled using the `terminal.ansi` system property, by setting it to `false`. ANSI library ------------ [Section titled “ANSI library”](https://docs.papermc.io/adventure/serializer/ansi/#ansi-library) The `AnsiComponentSerializer` is built upon a separate ANSI library, which deals with the lower-level ANSI escape sequence logic, and also allows for creating an ANSI converter for any kind of component, not just those by Adventure. Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/serializer/ansi/#tab-panel-27) * [Gradle (Groovy)](https://docs.papermc.io/adventure/serializer/ansi/#tab-panel-28) * [Maven](https://docs.papermc.io/adventure/serializer/ansi/#tab-panel-29) repositories { mavenCentral()} dependencies { implementation("net.kyori:ansi:1.1.1")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:ansi:1.1.1'} net.kyori ansi 1.1.1 ### Implementation usage [Section titled “Implementation usage”](https://docs.papermc.io/adventure/serializer/ansi/#implementation-usage) To begin with, you need to create a class that implements `StyleOps`, where `S` is the “style” type for your component type. This adapter class allows for the ANSI logic to access properties about the style. To actually begin conversion, create an instance of a `ANSIComponentRenderer`, by using one of the static methods, the simplest of which is `ANSIComponentRenderer.toString()`, passing it an instance of your `StyleOps` adapter described above. Then, you will need to traverse the structure of your component’s tree, using the `pushStyle()`, `text()` and `popStyle()` methods of the renderer instance. Finally, call `complete()` after traversing the tree has finished. The renderer’s job is now concluded. In the case of the `ToString` renderer, you can access the result using the `asString()` method. As described in the [ANSI Usage](https://docs.papermc.io/adventure/serializer/ansi/#usage) section, the library will, by default, try to guess the supported colors of the current environment. This may be overridden by passing a custom `ColorLevel` when creating the renderer, or by using the system properties as previously described. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Modded (Fabric and NeoForge shared API) | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/modded/#_top) Modded (Fabric and NeoForge shared API) ======================================= Starting with _Minecraft: Java Edition_ 1.21.2, Adventure is implemented using mostly shared code between NeoForge and Fabric. Each major version of Minecraft will usually require a new release of the platform. The platform supports all features, including localization and custom renderers. Dependency ---------- [Section titled “Dependency”](https://docs.papermc.io/adventure/platform/modded/#dependency) When building multi-loader mods, we often want to move as much code as possible into a loader-agnostic part of our projects. Adventure facilities this through the `net.kyori:adventure-platform-mod-shared` artifact. A second variant, `net.kyori:adventure-platform-mod-shared-fabric-repack`, is also published. This variant should be used when your common code is managed by `fabric-loom`. As with the rest of the Adventure projects, releases are distributed on Maven Central, and snapshots on Sonatype OSS: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/platform/modded/#tab-panel-17) * [Gradle (Groovy)](https://docs.papermc.io/adventure/platform/modded/#tab-panel-18) repositories { // for development builds maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { name = "central-snapshots" mavenContent { snapshotsOnly() } } // for releases mavenCentral()} dependencies { // Loom project modCompileOnly("net.kyori:adventure-platform-mod-shared-fabric-repack:6.8.0") // for Minecraft 1.21.11 // NeoGradle/ModDevGradle/VanillaGradle project compileOnly("net.kyori:adventure-platform-mod-shared:6.8.0") // for Minecraft 1.21.11} repositories { // for development builds maven { name = 'central-snapshots' url = 'https://central.sonatype.com/repository/maven-snapshots/' mavenContent { snapshotsOnly() } } // for releases mavenCentral()} dependencies { // Loom project modCompileOnly('net.kyori:adventure-platform-mod-shared-fabric-repack:6.8.0') // for Minecraft 1.21.11 // NeoGradle/ModDevGradle/VanillaGradle project compileOnly('net.kyori:adventure-platform-mod-shared:6.8.0') // for Minecraft 1.21.11} Basic use --------- [Section titled “Basic use”](https://docs.papermc.io/adventure/platform/modded/#basic-use) The easiest way to get started with this platform is to work with the Minecraft game objects that directly implement Adventure interfaces. This covers almost all cases where the default renderer is used. On Fabric, interface injection is used so that you can directly call interface methods on Minecraft objects (with loom 0.11+). On NeoForge, you must manually cast or use the helpers provided in `MinecraftAudiences`. The following Adventure interfaces are directly implemented: `Audience` * `net.minecraft.commands.CommandSourceStack`, `net.minecraft.server.MinecraftServer`, `net.minecraft.server.rcon.RconConsoleSource`, * `net.minecraft.server.level.ServerPlayer`, `net.minecraft.client.player.LocalPlayer` `AdventureCommandSourceStack` * `net.minecraft.commands.CommandSourceStack` `Sound.Emitter` * `net.minecraft.world.entity.Entity` `Sound.Type` * `net.minecraft.sounds.SoundEvent` `Identified` * `net.minecraft.world.entity.player.Player` `ComponentLike` * `net.minecraft.network.chat.Component` `Key` * `net.minecraft.resources.ResourceLocation` `Keyed` * `net.minecraft.resources.ResourceKey` `HoverEventSource` * `net.minecraft.world.entity.Entity`, * `net.minecraft.world.item.ItemStack` `SignedMessage.Signature` * `net.minecraft.network.chat.MessageSignature` Using these injections, getting started is as simple as: void greet(final ServerPlayer player) { Component message = Component.text() .content("Hello ") .append(player.get(Identity.DISPLAY_NAME) .get() .color(NamedTextColor.RED) ); player.sendMessage(message);} For more complex use cases, `MinecraftServerAudiences` or `MinecraftClientAudiences` provide additional API. ### Commands [Section titled “Commands”](https://docs.papermc.io/adventure/platform/modded/#commands) The platform provides custom argument types to specify `Key` and `Component` parameters in Brigadier commands. As an example, here’s a simple command that will echo whatever is provided as input: // A potential method to be in the mod initializer class aboveprivate static final String ARG_MESSAGE = "message"; void registerCommands(final CommandDispatcher dispatcher, final boolean isDedicated) { dispatcher.register(literal("echo").then(argument(ARG_MESSAGE, component()).executes(ctx -> { final Component message = component(ctx, ARG_MESSAGE); ((Audience) ctx.getSource()).sendMessage(Component.text("You said: ").append(message)); }));} Working with native types ------------------------- [Section titled “Working with native types”](https://docs.papermc.io/adventure/platform/modded/#working-with-native-types) Sadly, Adventure can’t provide API for every place chat components are used in the game. However, for areas not covered by the API in `Audience`, it’s possible to convert components between native and Adventure types. See certain native types which implement Adventure interfaces, and the methods on `MinecraftAudiences` for other available conversions. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Fabric | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/fabric/#_top) Fabric ====== Adventure supports Fabric on _Minecraft: Java Edition_ 1.16 and up, for both server-side and client-side use. Each major version of Minecraft will usually require a new release of the platform. The platform supports all features, including localization and custom renderers. When using at least version 5.3.0, this platform provides a _near-native_ experience by directly implementing Adventure interfaces on Minecraft classes where possible. Dependency ---------- [Section titled “Dependency”](https://docs.papermc.io/adventure/platform/fabric/#dependency) The Fabric platform is packaged as a mod, designed to be included in mods via jar-in-jar packaging. As with the rest of the Adventure projects, releases are distributed on Maven Central, and snapshots on Sonatype OSS: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/platform/fabric/#tab-panel-15) * [Gradle (Groovy)](https://docs.papermc.io/adventure/platform/fabric/#tab-panel-16) repositories { // for development builds maven(url = "https://s01.oss.sonatype.org/content/repositories/snapshots/") { name = "sonatype-oss-snapshots1" mavenContent { snapshotsOnly() } } // for releases mavenCentral()} dependencies { modImplementation(include("net.kyori:adventure-platform-fabric:6.8.0")!!) // for Minecraft 1.21.11} repositories { // for development builds maven { name = 'sonatype-oss-snapshots1' url = 'https://s01.oss.sonatype.org/content/repositories/snapshots/' mavenContent { snapshotsOnly() } } // for releases mavenCentral()} dependencies { modImplementation include('net.kyori:adventure-platform-fabric:6.8.0') // for Minecraft 1.21.11} The Fabric platform requires _fabric-api-base_ in order to provide the locale change event, _fabric-command-api-v2_ for the callback click event, and can optionally use [Colonel](https://gitlab.com/stellardrift/colonel) (or _fabric-networking-api-v1_) to allow the `Component` and `Key` argument types to be used on clients without the mod installed. There are no other dependencies. Basic use --------- [Section titled “Basic use”](https://docs.papermc.io/adventure/platform/fabric/#basic-use) The easiest way to get started with this platform is to work with the Minecraft game objects that directly implement Adventure interfaces (requires Loom 0.11 or newer). This covers almost all cases where the default renderer is used. The following Adventure interfaces are directly implemented: `Audience` * `net.minecraft.commands.CommandSourceStack`, `net.minecraft.server.MinecraftServer`, `net.minecraft.server.rcon.RconConsoleSource`, * `net.minecraft.server.level.ServerPlayer`, `net.minecraft.client.player.LocalPlayer` `Sound.Emitter` * `net.minecraft.world.entity.Entity` `Sound.Type` * `net.minecraft.sounds.SoundEvent` `Identified` * `net.minecraft.world.entity.player.Player` `ComponentLike` * `net.minecraft.network.chat.Component` `Key` * `net.minecraft.resources.ResourceLocation` `Keyed` * `net.minecraft.resources.ResourceKey` `HoverEventSource` * `net.minecraft.world.entity.Entity`, * `net.minecraft.world.item.ItemStack` `SignedMessage` * `net.minecraft.network.chat.PlayerChatMessage` `SignedMessage.Signature` * `net.minecraft.network.chat.MessageSignature` Additionally, all `Key`s created will be `ResourceLocation` instances (on Loader 0.14.0+) Using these injections, getting started is as simple as: void greet(final ServerPlayer player) { Component message = Component.text() .content("Hello ") .append(player.get(Identity.DISPLAY_NAME) .get() .color(NamedTextColor.RED) ); player.sendMessage(message);} For more complex use cases, `FabricServerAudiences` or `FabricClientAudiences` provide additional API. Server ------ [Section titled “Server”](https://docs.papermc.io/adventure/platform/fabric/#server) The logical-server side of the Fabric platform can be accessed any time a server is available, through a `MinecraftServerAudiences` instance. By default, translatable components will be rendered with the global translator, but a custom renderer can be passed when initializing the platform. All `AudienceProvider` interface methods are supported, except for the `permission` method. This will become supported as soon as Fabric gets a suitable permissions API. To get started with Adventure, set up an audience provider like this: public class MyMod implements ModInitializer { private volatile MinecraftServerAudiences adventure; public MinecraftServerAudiences adventure() { if (this.adventure == null) { throw new IllegalStateException("Tried to access Adventure without a running server!"); } return this.adventure; } @Override public void onInitialize() { // Register with the server lifecycle callbacks // This will ensure any platform data is cleared between game instances // This is important on the integrated server, where multiple server instances // can exist for one mod initialization. ServerLifecycleEvents.SERVER_STARTING.register(server -> this.adventure = MinecraftServerAudiences.of(server)); ServerLifecycleEvents.SERVER_STOPPED.register(server -> this.adventure = null); }} From here, audiences can be acquired for players and any other `CommandSource`. Specialized serializer instances are also available, to allow using game information in component serialization. ### Localization [Section titled “Localization”](https://docs.papermc.io/adventure/platform/fabric/#localization) As part of the platform’s translation support, the `PlayerLocales.CHANGED_EVENT` callback will be called any time a player on the server receives an updated language from their client, and allows accessing the current locale for a player. ### Commands [Section titled “Commands”](https://docs.papermc.io/adventure/platform/fabric/#commands) The Fabric platform provides custom argument types to specify `Key` and `Component` parameters in Brigadier commands, and has helpers to easily get an `Audience` from a `CommandSourceStack` (yarn: `ServerCommandSource`) instance. As an example, here’s a simple command that will echo whatever is provided as input: // A potential method to be in the mod initializer class aboveprivate static final String ARG_MESSAGE = "message"; void registerCommands(final CommandDispatcher dispatcher, final boolean isDedicated) { dispatcher.register(literal("echo").then(argument(ARG_MESSAGE, component()).executes(ctx -> { final Component message = component(ctx, ARG_MESSAGE); ctx.getSource().sendMessage(Component.text("You said: ").append(message)); }));} Client ------ [Section titled “Client”](https://docs.papermc.io/adventure/platform/fabric/#client) Special for the Fabric platform, purely client-side operations are supported. The setup is less involved than it is for the server, since the client is a singleton, and there is only one subject that can be acted on: the client’s player. This means that for most users the `MinecraftClientAudiences` object can be treated as a singleton. The only exception is users using a custom renderer. This makes using Adventure audiences fairly simple, as this code example shows: void doThing() { // Get the audience final Audience client = MinecraftClientAudiences.of().audience(); // Do something. This will only work when the player is in game. client.sendMessage(Component.text("meow", NamedTextColor.DARK_PURPLE));} The full functionality of the `Audience` interface is available, including localization! Working with native types ------------------------- [Section titled “Working with native types”](https://docs.papermc.io/adventure/platform/fabric/#working-with-native-types) Sadly, Adventure can’t provide API for every place chat components are used in the game. However, for areas not covered by the API in `Audience`, it’s possible to convert components between native and Adventure types. See certain native types which implement Adventure interfaces, and the methods on `FabricAudiences` for other available conversions. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Player list/Tab list | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/tablist/#_top) Player list/Tab list ==================== Adventure only supports changing the header (above the players) and footer (below the players) of the tab list. ![Image showing a tab list from a multiplayer server with the header and footer encased, shown through the vanilla Minecraft client](https://docs.papermc.io/_astro/tablist.B62gkSy1_ZNX63Y.webp) **Usage** With any `Audience` use `Audience.sendPlayerListHeader(Component)`, `Audience.sendPlayerListFooter(Component)` and/or `Audience.sendPlayerListHeaderAndFooter(Component, Component)`. Whether sending a header or footer by itself will display another existing header or footer will vary depending on which platform you are working on. Servers will most likely support keeping headers or footers when sending them separately, while proxies are more likely to only let you send everything at once. **Examples** public void onPlayerJoin(final Audience player) { final Component header = Component.text("My Cool Server", NamedTextColor.BLUE); final Component footer = Component.text("It is: today!"); player.sendPlayerListHeaderAndFooter(header, footer);} Depending on your platform this next example might display an existing header as well public void onDayChange(final Audience server) { final Component footer = Component.text("It is: tomorrow!"); server.sendPlayerListFooter(footer);} Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # JSON | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/serializer/json/#_top) JSON ==== The JSON serializer provides a common interface for serializer implementations that translate between a Component and JSON strings. This allows a library to support any underlying JSON library that an application may want to use. Use --- [Section titled “Use”](https://docs.papermc.io/adventure/serializer/json/#use) The JSON serializer works similar to all others, providing the basic serialize and deserialize operations: // Component to textfinal String jsonText = JSONComponentSerializer.json().serialize(Component.text("Hello world", NamedTextColor.LIGHT_PURPLE)); // JSON string to componentfinal Component comp = JSONComponentSerializer.json().deserialize(jsonText); Additionally, there is a `JSONComponentSerializer.builder()` available for advanced use that requires configuring legacy compatibility options. Known implementations --------------------- [Section titled “Known implementations”](https://docs.papermc.io/adventure/serializer/json/#known-implementations) | Name | Description | | --- | --- | | [adventure-text-serializer-gson](https://docs.papermc.io/adventure/serializer/gson) | A mature serializer working with Google’s Gson library. | Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Gson | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/serializer/gson/#_top) Gson ==== The Gson text serializer converts chat components to their JSON representation and back using the Gson library. If you are interested in sending a chat component for display in a Minecraft client, or want to support advanced chat component features, you should use the Gson text serializer. An average user of this text serializer will typically want to only deserialize a component from an external source - serialization is done automatically by the [Platforms](https://docs.papermc.io/adventure/platform) when the component is sent to the user. Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/serializer/gson/#tab-panel-30) * [Gradle (Groovy)](https://docs.papermc.io/adventure/serializer/gson/#tab-panel-31) * [Maven](https://docs.papermc.io/adventure/serializer/gson/#tab-panel-32) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-text-serializer-gson:5.2.0")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-text-serializer-gson:5.2.0'} net.kyori adventure-text-serializer-gson 5.2.0 Usage ----- [Section titled “Usage”](https://docs.papermc.io/adventure/serializer/gson/#usage) In Minecraft 1.16, Mojang made several major changes to the JSON chat format, adding RGB chat colors and changing how hover events are serialized. Components generated for older versions of Minecraft will still be able to be displayed in a 1.16 client, however components serialized for a 1.16 client will not be able to be displayed in a Minecraft 1.15.2 client or lower. To get a serializer that works with 1.16 clients and above, use `GsonComponentSerializer.gson()`. To get a serializer that works with all versions of Minecraft that support text components, use `GsonComponentSerializer.colorDownsamplingGson()`. This serializer downsamples RGB colors to the closest Mojang legacy color and serializes hover events in a way that is backwards compatible with older clients. ### Which serializer should I use? [Section titled “Which serializer should I use?”](https://docs.papermc.io/adventure/serializer/gson/#which-serializer-should-i-use) If all you’re doing is loading and saving components to a configuration file or a database, you probably want to use the default 1.16 serializer. If you’re looking to send a component to a client, first consider whether you can one of the provided platforms. If you can’t use a platform, generally you should prefer the default serializer for deserializing components (as it is backwards-compatible), and make a decision on whether to use the default or the color downsampling serializer based on the version the client is on. ### Advanced usage [Section titled “Advanced usage”](https://docs.papermc.io/adventure/serializer/gson/#advanced-usage) The Gson serializer exposes both the backing `Gson` instance and a populator that allows registering Adventure serializers on any `GsonBuilder` instance. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Sound | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/sound/#_top) Sound ===== Adventure contains an API to play any built-in or resource pack-provided sound. Note that not all platforms implement playing sound. Constructing a Sound -------------------- [Section titled “Constructing a Sound”](https://docs.papermc.io/adventure/sound/#constructing-a-sound) Sounds are composed of: * A Key (also known as `Identifier` or `ResourceLocation`) that decides which sound to play. Any custom sounds from resource packs can be used. If a client does not know about sounds, it will ignore the sound (though a warning will be printed to the client log). * A Sound source, used to tell the client what type of sound its hearing. The clients sound settings are also attributed to a source. * A number, determining the radius where the sound can be heard * A number from 0 to 2 determining the pitch the sound will be played at **Examples:** // Create a built-in sound using standard volume and pitchSound musicDisc = Sound.sound(Key.key("music_disc.13"), Sound.Source.MUSIC, 1f, 1f); // Create a sound from our resource pack with a higher pitchSound myCustomSound = Sound.sound(Key.key("adventure", "rawr"), Sound.Source.AMBIENT, 1f, 1.1f); Playing a Sound --------------- [Section titled “Playing a Sound”](https://docs.papermc.io/adventure/sound/#playing-a-sound) Once you’ve created a sound, they can be played to an audience using multiple methods: // Play a sound at the location of the audienceaudience.playSound(sound); // Play a sound at a specific locationaudience.playSound(sound, 100, 0, 150); // Play a sound that follows the audience memberaudience.playSound(sound, Sound.Emitter.self()); // Play a sound that follows another emitter (usually an entity)audience.playSound(sound, someEntity); Stopping Sounds --------------- [Section titled “Stopping Sounds”](https://docs.papermc.io/adventure/sound/#stopping-sounds) A sound stop will stop the chosen sounds — ranging from every sound the client is playing, to specific named sounds. public void stopMySound(final @NonNull Audience target) {// Stop a sound for the targettarget.stopSound(SoundStop.named(Key.key("music_disc.13"));// Stop all weather sounds for the targettarget.stopSound(SoundStop.source(Sound.Source.WEATHER));// Stop all sounds for the targettarget.stopSound(SoundStop.all()); Sound stops can be constructed using the methods in the example block above. Alternatively, they can be constructed directly from a sound. // Get a sound stop that will stop a specific soundmySound.asStop(); // Sounds can also be stopped directly using the stopSound methodaudience.stopSound(mySound); Creating a custom sound ----------------------- [Section titled “Creating a custom sound”](https://docs.papermc.io/adventure/sound/#creating-a-custom-sound) Use the `sounds.json` file to define sounds in a resource pack. Further reading about this limits can be done at the [Minecraft Wiki](https://minecraft.wiki/w/Sounds.json) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Titles | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/titles/#_top) Titles ====== Constructing a Title -------------------- [Section titled “Constructing a Title”](https://docs.papermc.io/adventure/titles/#constructing-a-title) Titles are composed of: * A component used for the main title * A component used for the subtitle * Optionally, a `Title.Times` object can be used to determine the fade-in, stay on screen and fade-out durations **Examples:** public void showMyTitle(final @NonNull Audience target) { final Component mainTitle = Component.text("This is the main title", NamedTextColor.WHITE); final Component subtitle = Component.text("This is the subtitle", NamedTextColor.GRAY); // Creates a simple title with the default values for fade-in, stay on screen and fade-out durations final Title title = Title.title(mainTitle, subtitle); // Send the title to your audience target.showTitle(title);} public void showMyTitleWithDurations(final @NonNull Audience target) { final Title.Times times = Title.Times.times(Duration.ofMillis(500), Duration.ofMillis(3000), Duration.ofMillis(1000)); // Using the times object this title will use 500ms to fade in, stay on screen for 3000ms and then fade out for 1000ms final Title title = Title.title(Component.text("Hello!"), Component.empty(), times); // Send the title, you can also use Audience#clearTitle() to remove the title at any time target.showTitle(title);} Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # adventure-platform | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/version-history/adventure-platform/#_top) adventure-platform ================== v4.4.1 ------ [Section titled “v4.4.1”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.4.1) Released on Jul 30, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.4.1) This is a patch release that adds initial support for 1.21.6/1.21.7. What's Changed -------------- * Bukkit - Update MinecraftComponentSerializer for 1.21.6/7 by [@bloodmc](https://github.com/bloodmc) in [#212](https://github.com/PaperMC/adventure-platform/pull/212) New Contributors ---------------- * [@bloodmc](https://github.com/bloodmc) made their first contribution in [#212](https://github.com/PaperMC/adventure-platform/pull/212) **Full Changelog**: [v4.4.0...v4.4.1](https://github.com/PaperMC/adventure-platform/compare/v4.4.0...v4.4.1) * * * v4.4.0 ------ [Section titled “v4.4.0”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.4.0) Released on May 10, 2025 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.4.0) This release bumps the Adventure version used in order to support 1.21.5 on legacy platforms. What's Changed -------------- ### Other * Support getLocale returning a Locale by [@Pablete1234](https://github.com/Pablete1234) in [#202](https://github.com/PaperMC/adventure-platform/pull/202) * 1.21.5 support for platform-bukkit by [@MiniDigger](https://github.com/MiniDigger) in [#206](https://github.com/PaperMC/adventure-platform/pull/206) New Contributors ---------------- * [@Pablete1234](https://github.com/Pablete1234) made their first contribution in [#202](https://github.com/PaperMC/adventure-platform/pull/202) **Full Changelog**: [v4.3.4...v4.4.0](https://github.com/PaperMC/adventure-platform/compare/v4.3.4...v4.4.0) * * * v4.3.4 ------ [Section titled “v4.3.4”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.3.4) Released on Aug 7, 2024 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.3.4) This is a minor bugfix release that aims to fix some issues in certain environments. What's Changed -------------- ### 🐛 Fixes * Fixed MinecraftComponentSerializer not working due to relocation by [@re-ovo](https://github.com/re-ovo) in [#177](https://github.com/PaperMC/adventure-platform/pull/177) * Fix removed ResourceLocation constructor by [@56738](https://github.com/56738) in [#188](https://github.com/PaperMC/adventure-platform/pull/188) New Contributors ---------------- * [@re-ovo](https://github.com/re-ovo) made their first contribution in [#177](https://github.com/PaperMC/adventure-platform/pull/177) **Full Changelog**: [v4.3.3...v4.3.4](https://github.com/PaperMC/adventure-platform/compare/v4.3.3...v4.3.4) * * * v4.3.3 ------ [Section titled “v4.3.3”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.3.3) Released on Jun 2, 2024 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.3.3) This is a patch release to add support for Minecraft 1.20.5/1.20.6, for those who still choose to support legacy plataforms. What's Changed -------------- ### ✨ Features * Bukkit 1.20.5 support by [@56738](https://github.com/56738) in [#163](https://github.com/PaperMC/adventure-platform/pull/163) * BungeeCord: BossBar compatibilty with BungeeCord 1.20-R0.2 and newer by [@bivashy](https://github.com/bivashy) in [#153](https://github.com/PaperMC/adventure-platform/pull/153) ### 🐛 Fixes * Fix tab list header/footer on Paper 1.20.6 by [@jpenilla](https://github.com/jpenilla) in [#171](https://github.com/PaperMC/adventure-platform/pull/171) * Set player locale when creating Audience by [@CubBossa](https://github.com/CubBossa) in [#160](https://github.com/PaperMC/adventure-platform/pull/160) ### Other * fix snapshot badge by [@powercasgamer](https://github.com/powercasgamer) in [#166](https://github.com/PaperMC/adventure-platform/pull/166) * Fix javadoc generation by [@56738](https://github.com/56738) in [#168](https://github.com/PaperMC/adventure-platform/pull/168) New Contributors ---------------- * [@powercasgamer](https://github.com/powercasgamer) made their first contribution in [#166](https://github.com/PaperMC/adventure-platform/pull/166) * [@bivashy](https://github.com/bivashy) made their first contribution in [#153](https://github.com/PaperMC/adventure-platform/pull/153) * [@CubBossa](https://github.com/CubBossa) made their first contribution in [#160](https://github.com/PaperMC/adventure-platform/pull/160) **Full Changelog**: [v4.3.2...v4.3.3](https://github.com/PaperMC/adventure-platform/compare/v4.3.2...v4.3.3) * * * v4.3.2 ------ [Section titled “v4.3.2”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.3.2) Released on Dec 21, 2023 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.3.2) This is a patch release to add support for 1.20.3 and 1.20.4 on the Bukkit platform. What's Changed -------------- * Fix MinecraftComponentSerializer on 1.20.3 by [@56738](https://github.com/56738) in [#144](https://github.com/PaperMC/adventure-platform/pull/144) **Full Changelog**: [v4.3.1...v4.3.2](https://github.com/PaperMC/adventure-platform/compare/v4.3.1...v4.3.2) * * * v4.3.1 ------ [Section titled “v4.3.1”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.3.1) Released on Sep 29, 2023 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.3.1) This is a bugfix release to add support for Minecraft 1.20.2 on the Bukkit platform. What's Changed -------------- * Fix CraftBukkitFacet on 1.20.2 by [@56738](https://github.com/56738) in [#140](https://github.com/PaperMC/adventure-platform/pull/140) New Contributors ---------------- * [@56738](https://github.com/56738) made their first contribution in [#140](https://github.com/PaperMC/adventure-platform/pull/140) **Full Changelog**: [v4.3.0...v4.3.1](https://github.com/PaperMC/adventure-platform/compare/v4.3.0...v4.3.1) * * * v4.3.0 ------ [Section titled “v4.3.0”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.3.0) Released on Mar 16, 2023 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.3.0) This release adds full support for 1.19.4 on the Bukkit platform (though most functionality should work even on 4.2.0). What's Changed -------------- * fix: 1.19.4 bound chat types by [@Machine-Maker](https://github.com/Machine-Maker) in [#128](https://github.com/PaperMC/adventure-platform/pull/128) New Contributors ---------------- * [@neziw](https://github.com/neziw) made their first contribution in [#124](https://github.com/PaperMC/adventure-platform/pull/124) **Full Changelog**: [v4.2.0...v4.3.0](https://github.com/PaperMC/adventure-platform/compare/v4.2.0...v4.3.0) * * * v4.2.0 ------ [Section titled “v4.2.0”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.2.0) Released on Dec 9, 2022 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.2.0) What's Changed -------------- * fix: CraftBukkit BossBar for 1.18+ by [@Machine-Maker](https://github.com/Machine-Maker) in [#94](https://github.com/PaperMC/adventure-platform/pull/94) * Bump adventure to 4.12 and use sound seed when present by [@jpenilla](https://github.com/jpenilla) in [#112](https://github.com/PaperMC/adventure-platform/pull/112) * 1.19.3 chat for bukkit by [@Machine-Maker](https://github.com/Machine-Maker) in [#113](https://github.com/PaperMC/adventure-platform/pull/113) * Fix craftbukkit entity sound facet for 1.19.3 by [@Machine-Maker](https://github.com/Machine-Maker) in [#117](https://github.com/PaperMC/adventure-platform/pull/117) **Full Changelog**: [v4.1.2...v4.2.0](https://github.com/PaperMC/adventure-platform/compare/v4.1.2...v4.2.0) * * * v4.1.2 ------ [Section titled “v4.1.2”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.1.2) Released on Aug 3, 2022 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.1.2) What's Changed -------------- * Fix ViaFacet component type by [@kennytv](https://github.com/kennytv) in [#95](https://github.com/PaperMC/adventure-platform/pull/95) * fix: CraftBukkit Chat facet for 1.19.1 by [@Machine-Maker](https://github.com/Machine-Maker) in [#98](https://github.com/PaperMC/adventure-platform/pull/98) * fix: CraftBukkit EntitySound for 1.19+ by [@Machine-Maker](https://github.com/Machine-Maker) in [#99](https://github.com/PaperMC/adventure-platform/pull/99) **Full Changelog**: [v4.1.1...v4.1.2](https://github.com/PaperMC/adventure-platform/compare/v4.1.1...v4.1.2) * * * adventure-platform 4.1.1 ------------------------ [Section titled “adventure-platform 4.1.1”](https://docs.papermc.io/adventure/version-history/adventure-platform/#v4.1.1) Released on Jun 12, 2022 - [GitHub](https://github.com/PaperMC/adventure-platform/releases/tag/v4.1.1) What's Changed -------------- * fix: CraftBukkit Chat facet for 1.19 by [@Machine-Maker](https://github.com/Machine-Maker) in [#93](https://github.com/PaperMC/adventure-platform/pull/93) New Contributors ---------------- * [@Machine-Maker](https://github.com/Machine-Maker) made their first contribution in [#93](https://github.com/PaperMC/adventure-platform/pull/93) **Full Changelog**: [v4.1.0...v4.1.1](https://github.com/PaperMC/adventure-platform/compare/v4.1.0...v4.1.1) * * * Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Plain | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/serializer/plain/#_top) Plain ===== The plain text serializer converts chat components to their plain-text representation and back. It is thus the simplest text serializer in Adventure. This serializer is useful for supporting legacy clients, logging, clearing formatting from a component that originates from external source, and provides a small, self-contained example of a text serializer. The plain text serializer, by its nature, does not support any advanced features, including color, hover and click events, URL linking, or insertions. If advanced features are desired, consider using [MiniMessage](https://docs.papermc.io/adventure/minimessage) . Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/serializer/plain/#tab-panel-36) * [Gradle (Groovy)](https://docs.papermc.io/adventure/serializer/plain/#tab-panel-37) * [Maven](https://docs.papermc.io/adventure/serializer/plain/#tab-panel-38) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-text-serializer-plain:5.2.0")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-text-serializer-plain:5.2.0'} net.kyori adventure-text-serializer-plain 5.2.0 Usage ----- [Section titled “Usage”](https://docs.papermc.io/adventure/serializer/plain/#usage) This produces a default instance that silently ignores keybind and translatable components. You can also construct your own `PlainTextComponentSerializer` that maps the components to some plain-text representation. The deserialization of plain text is equivalent to `Component.text(string)`. No preprocessing is done on the input. The deserialization is implemented in order to provide API consistency. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Platforms | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/#_top) Platforms ========= Adventure integrates with many of the Minecraft platforms out there. Some platforms support Adventure natively, but other legacy platforms have their own types and need an adapter to handle Adventure types. To enable you to use Adventure with these platforms, Adventure provides a number of platform-specific adapters to allow you to obtain `Audience` instances from native user types. ### Content: [Section titled “Content:”](https://docs.papermc.io/adventure/platform/#content) * [Native support](https://docs.papermc.io/adventure/platform/native) * [Modded (Fabric and NeoForge shared API)](https://docs.papermc.io/adventure/platform/modded) * [Dependency](https://docs.papermc.io/adventure/platform/modded#dependency) * [Basic use](https://docs.papermc.io/adventure/platform/modded#basic-use) * [Working with native types](https://docs.papermc.io/adventure/platform/modded#working-with-native-types) * [Fabric](https://docs.papermc.io/adventure/platform/fabric) * [Dependency](https://docs.papermc.io/adventure/platform/fabric#dependency) * [Basic use](https://docs.papermc.io/adventure/platform/fabric#basic-use) * [Server](https://docs.papermc.io/adventure/platform/fabric#server) * [Client](https://docs.papermc.io/adventure/platform/fabric#dependency) * [Working with native types](https://docs.papermc.io/adventure/platform/fabric#working-with-native-types) * [NeoForge](https://docs.papermc.io/adventure/platform/neoforge) * [Dependency](https://docs.papermc.io/adventure/platform/neoforge#dependency) * [Basic use](https://docs.papermc.io/adventure/platform/neoforge#basic-use) * [Server](https://docs.papermc.io/adventure/platform/neoforge#server) * [Commands](https://docs.papermc.io/adventure/platform/neoforge#commands) * [Client](https://docs.papermc.io/adventure/platform/neoforge#dependency) * [Implementing platforms](https://docs.papermc.io/adventure/platform/implementing) * [Services](https://docs.papermc.io/adventure/platform/implementing#services) * [Conventional behaviors](https://docs.papermc.io/adventure/platform/implementing#conventional-behaviors) ### Legacy platforms [Section titled “Legacy platforms”](https://docs.papermc.io/adventure/platform/#legacy-platforms) * [Bukkit](https://docs.papermc.io/adventure/platform/bukkit) * [Usage](https://docs.papermc.io/adventure/platform/bukkit#usage) * [Component serializers](https://docs.papermc.io/adventure/platform/bukkit#component-serializers) * [BungeeCord](https://docs.papermc.io/adventure/platform/bungeecord) * [Usage](https://docs.papermc.io/adventure/platform/bungeecord#usage) * [Component serializers](https://docs.papermc.io/adventure/platform/bungeecord#component-serializers) * [SpongeAPI](https://docs.papermc.io/adventure/platform/spongeapi) * [Usage](https://docs.papermc.io/adventure/platform/spongeapi#usage) * [ViaVersion](https://docs.papermc.io/adventure/platform/viaversion) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # NeoForge | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/platform/neoforge/#_top) NeoForge ======== Adventure supports NeoForge on _Minecraft: Java Edition_ 1.21 and up, for both server-side and client-side use. Each major version of Minecraft will usually require a new release of the platform. The platform supports all features, including localization and custom renderers. Dependency ---------- [Section titled “Dependency”](https://docs.papermc.io/adventure/platform/neoforge/#dependency) The NeoForge platform is packaged as a mod, designed to be included in mods via jar-in-jar packaging. As with the rest of the Adventure projects, releases are distributed on Maven Central, and snapshots on Sonatype OSS: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/platform/neoforge/#tab-panel-19) * [Gradle (Groovy)](https://docs.papermc.io/adventure/platform/neoforge/#tab-panel-20) repositories { // for development builds maven(url = "https://s01.oss.sonatype.org/content/repositories/snapshots/") { name = "sonatype-oss-snapshots1" mavenContent { snapshotsOnly() } } // for releases mavenCentral()} dependencies { modImplementation(include("net.kyori:adventure-platform-neoforge:6.8.0")!!) // for Minecraft 1.21.11} repositories { // for development builds maven { name = 'sonatype-oss-snapshots1' url = 'https://s01.oss.sonatype.org/content/repositories/snapshots/' mavenContent { snapshotsOnly() } } // for releases mavenCentral()} dependencies { modImplementation include('net.kyori:adventure-platform-neoforge:6.8.0') // for Minecraft 1.21.11} Basic use --------- [Section titled “Basic use”](https://docs.papermc.io/adventure/platform/neoforge/#basic-use) See [Modded (Fabric and NeoForge shared API)](https://docs.papermc.io/adventure/platform/modded) for usage details common between NeoForge and Fabric. Server ------ [Section titled “Server”](https://docs.papermc.io/adventure/platform/neoforge/#server) The logical-server side of the modded platform can be accessed any time a server is available, through a `MinecraftServerAudiences` instance. By default, translatable components will be rendered with the global translator, but a custom renderer can be passed when initializing the platform. All `AudienceProvider` interface methods are supported. To get started with Adventure, set up an audience provider like this: @Mod("my_mod")public class MyMod { private volatile MinecraftServerAudiences adventure; public MinecraftServerAudiences adventure() { if (this.adventure == null) { throw new IllegalStateException("Tried to access Adventure without a running server!"); } return this.adventure; } public MyMod() { // Register with the server lifecycle callbacks // This will ensure any platform data is cleared between game instances // This is important on the integrated server, where multiple server instances // can exist for one mod initialization. NeoForge.EVENT_BUS.addListener((ServerStartingEvent e) -> this.adventure = MinecraftServerAudiences.of(e.getServer()) ); NeoForge.EVENT_BUS.addListener((ServerStoppedEvent e) -> this.adventure = null ); }} From here, audiences can be acquired for players and any other `CommandSource`. Specialized serializer instances are also available, to allow using game information in component serialization. Commands -------- [Section titled “Commands”](https://docs.papermc.io/adventure/platform/neoforge/#commands) The NeoForge platform includes a method to register the `KeyArgumentType` and `ComponentArgumentType`: * `AdventureArgumentTypes.register();` This should be called from the constructor of your `@Mod`\-annotated class. Registering the argument types on the server will require all clients that join to have the argument types registered as well. Client ------ [Section titled “Client”](https://docs.papermc.io/adventure/platform/neoforge/#client) Special for the modded platform, purely client-side operations are supported. The setup is less involved than it is for the server, since the client is a singleton, and there is only one subject that can be acted on: the client’s player. This means that for most users the `MinecraftClientAudiences` object can be treated as a singleton. The only exception is users using a custom renderer. This makes using Adventure audiences fairly simple, as this code example shows: void doThing() { // Get the audience final Audience client = MinecraftClientAudiences.of().audience(); // Do something. This will only work when the player is ingame. client.sendMessage(Component.text("meow", NamedTextColor.DARK_PURPLE));} The full functionality of the `Audience` interface is available, including localization! Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Legacy | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/serializer/legacy/#_top) Legacy ====== The legacy text serializer converts text to and from the traditional chat format used in Minecraft prior to Minecraft 1.7, and continues to be used to this day for its familiarity to server owners. The legacy text serializer does not support most advanced features, including hover and click events, components besides text components, and insertions. RGB colors are supported (see more in the [RGB support](https://docs.papermc.io/adventure/serializer/legacy/#rgb-support) section) and URLs can be transformed into clickable components if explicitly requested (note, however, that click events containing a URL will _not_ be serialized). If advanced features are desired, consider using [MiniMessage](https://docs.papermc.io/adventure/minimessage) . Declaring the dependency: * [Gradle (Kotlin)](https://docs.papermc.io/adventure/serializer/legacy/#tab-panel-33) * [Gradle (Groovy)](https://docs.papermc.io/adventure/serializer/legacy/#tab-panel-34) * [Maven](https://docs.papermc.io/adventure/serializer/legacy/#tab-panel-35) repositories { mavenCentral()} dependencies { implementation("net.kyori:adventure-text-serializer-legacy:5.2.0")} repositories { mavenCentral()} dependencies { implementation 'net.kyori:adventure-text-serializer-legacy:5.2.0'} net.kyori adventure-text-serializer-legacy 5.2.0 Usage ----- [Section titled “Usage”](https://docs.papermc.io/adventure/serializer/legacy/#usage) The legacy text serializer is accessed using the `LegacyComponentSerializer`. The default pre-provided serializers include one that uses the section symbol (§) (for display in old clients) and another that uses an ampersand (&) typically used in configuration and commands to specify color codes. The default configuration for the legacy text serializer will deserialize all three of the RGB formats supported by Adventure but will only serialize legacy Mojang colors (downsampling to the nearest color as needed) and does not transform URLs in text to links. You can configure an instance to automatically add click events to URLs in components and allow the serializer to serialize RGB colors in either the Adventure RGB format or the BungeeCord RGB format using the builder. RGB support ----------- [Section titled “RGB support”](https://docs.papermc.io/adventure/serializer/legacy/#rgb-support) The legacy serializer supports deserializing three different formats: * Legacy Mojang color and formatting codes (such as `§a` or `§l`). * An Adventure-specific RGB format that is intended to be easy to edit (such as `§#a25981`). * A BungeeCord RGB color code format that is backwards compatible with older deserialization routines but is difficult to manipulate and makes it the user’s responsibility to assign a fallback for non-RGB clients (such as `§x§a§2§5§9§8§1`). The legacy serializer downsamples RGB colors by default, but you can create a serializer that serializes RGB colors in either the Adventure or BungeeCord RGB formats using the builder. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # adventure | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/version-history/adventure/#_top) adventure ========= 🌏 Adventure 5.2.0 ------------------ [Section titled “🌏 Adventure 5.2.0”](https://docs.papermc.io/adventure/version-history/adventure/#v5.2.0) Released on Jun 27, 2026 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v5.2.0) Adventure 5.2.0 is primary a bugfix update to restore a break in binary compatibility for users compiling against 4.x but running against 5.x. This issue was caused by the removal of `BuildableComponent`, which would cause a `MethodNotFoundException` for those using component builders. `BuildableComponent` will remain deprecated and will be fully removed in 6.0 with no replacement. The only use of `BuildableComponent` in 4.x was to turn a component into a builder (which involved casting to `BuildableComponent`), but this is now solved by the promotion of the `toBuilder` method to the root `Component` class. The fix for this restores the interface to the component hierarchy and adds another compile-time synthetic bridge to fix code compiling against 4.x. The bridge methods will be removed in 6.x so we still encourage everyone to update to 5.x. What's Changed -------------- ### ✨ Features * Easier way to create object components by [@kezz](https://github.com/kezz) in [#1421](https://github.com/PaperMC/adventure/pull/1421) ### 🐛 Fixes * Add back `BuildableComponent` by [@jpenilla](https://github.com/jpenilla) in [#1432](https://github.com/PaperMC/adventure/pull/1432) * Change gpg key by [@MiniDigger](https://github.com/MiniDigger) in [#1423](https://github.com/PaperMC/adventure/pull/1423) **Full Changelog**: [v5.1.1...v5.2.0](https://github.com/PaperMC/adventure/compare/v5.1.1...v5.2.0) * * * 🌏 Adventure 5.1.1 ------------------ [Section titled “🌏 Adventure 5.1.1”](https://docs.papermc.io/adventure/version-history/adventure/#v5.1.1) Released on May 12, 2026 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v5.1.1) Adventure 5.1.1 is a bug-fix update to correct the publishing setup for Maven consumers. **Full Changelog**: [v5.1.0...v5.1.1](https://github.com/PaperMC/adventure/compare/v5.1.0...v5.1.1) * * * 🌏 Adventure 5.1.0 ------------------ [Section titled “🌏 Adventure 5.1.0”](https://docs.papermc.io/adventure/version-history/adventure/#v5.1.0) Released on May 11, 2026 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v5.1.0) Adventure 5.1.0 is primarily a bug-fix update for some unintentional breaks caused by the 5.0 release. This update also includes stricter validation for key namespaces and click event construction, and also adds new methods to check the validity of click event payloads. Although the validation added is generally stricter than older Minecraft versions, the validation is still correct for all versions. If you have issues with the validation added, please open an issue! What's Changed -------------- ### ✨ Features * Add pages-only constructor to BookImpl by [@Privatech38](https://github.com/Privatech38) in [#1372](https://github.com/PaperMC/adventure/pull/1372) * Add intersex inclusive pride flag to PrideTag by [@me4502](https://github.com/me4502) in [#1405](https://github.com/PaperMC/adventure/pull/1405) * Add validation for player head name by [@kezz](https://github.com/kezz) in [#1417](https://github.com/PaperMC/adventure/pull/1417) * Disallow `..` as a namespace by [@kezz](https://github.com/kezz) in [#1416](https://github.com/PaperMC/adventure/pull/1416) * Simple validation click events on creation by [@kezz](https://github.com/kezz) in [#1418](https://github.com/PaperMC/adventure/pull/1418) * Add validation for invalid change page click events by [@kezz](https://github.com/kezz) in [#1419](https://github.com/PaperMC/adventure/pull/1419) ### 🐛 Fixes * Restore legacy NBT hover events in MiniMessage by [@Privatech38](https://github.com/Privatech38) in [#1403](https://github.com/PaperMC/adventure/pull/1403) * Fix SPI when using modules by [@kermandev](https://github.com/kermandev) in [#1396](https://github.com/PaperMC/adventure/pull/1396) * Restore missing negated shorthand decoration tags by [@kezz](https://github.com/kezz) in [#1413](https://github.com/PaperMC/adventure/pull/1413) * Emit value for event payloads when using camel case by [@kezz](https://github.com/kezz) in [#1414](https://github.com/PaperMC/adventure/pull/1414) * Fix ComponentBuilder#build ABI compatibility by [@kezz](https://github.com/kezz) in [#1407](https://github.com/PaperMC/adventure/pull/1407) ### 🏃 Performance * Speedup \*Color#asHexString by [@kermandev](https://github.com/kermandev) in [#1386](https://github.com/PaperMC/adventure/pull/1386) ### 📚 Documentation * chore: replace wiki.vg links by [@RealBauHD](https://github.com/RealBauHD) in [#1402](https://github.com/PaperMC/adventure/pull/1402) New Contributors ---------------- * [@me4502](https://github.com/me4502) made their first contribution in [#1405](https://github.com/PaperMC/adventure/pull/1405) **Full Changelog**: [v5.0.1...v5.1.0](https://github.com/PaperMC/adventure/compare/v5.0.1...v5.1.0) * * * 🌏 Adventure 5.0.1 ------------------ [Section titled “🌏 Adventure 5.0.1”](https://docs.papermc.io/adventure/version-history/adventure/#v5.0.1) Released on Apr 16, 2026 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v5.0.1) 5.0.1 is a bugfix update containing a fix for leftover checker annotations and some minor edits to the Javadocs. We are now publishing an aggregate Javadoc for all core Adventure libraries (in this repo) available on the standard PaperMC Javadoc portal at [https://papermc.io/javadocs/](https://papermc.io/javadocs/) . What's Changed -------------- ### 🐛 Fixes * chore(configurate-4): replace checkerframework annotations by [@Strokkur424](https://github.com/Strokkur424) in [#1398](https://github.com/PaperMC/adventure/pull/1398) ### 📚 Documentation * chore(build): Publish aggregate javadoc jar by [@kezz](https://github.com/kezz) in [#1399](https://github.com/PaperMC/adventure/pull/1399) * chore(docs): Fix incorrect docs for ShadowColor#alpha by [@kezz](https://github.com/kezz) in [#1400](https://github.com/PaperMC/adventure/pull/1400) * chore(docs): Remove incorrect annotations from ForwardingAudience.Single methods by [@kezz](https://github.com/kezz) in [#1401](https://github.com/PaperMC/adventure/pull/1401) **Full Changelog**: [v5.0.0...v5.0.1](https://github.com/PaperMC/adventure/compare/v5.0.0...v5.0.1) * * * 🌏 Adventure 5.0.0 ------------------ [Section titled “🌏 Adventure 5.0.0”](https://docs.papermc.io/adventure/version-history/adventure/#v5.0.0) Released on Apr 16, 2026 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v5.0.0) Adventure 5.0.0 is a major update to the Adventure library, including an updated Java version, removal of deprecations, and other breaking changes. The 5.0.0 update represents a major milestone in the development of the Adventure library, with 7,000+ additions and 12,000+ deletions across over 500 files. Important Although we have tried our hardest to avoid unnecessary breaking changes, we do expect this update to contain bugs or unintentional breaking changes and the Adventure team is prepared to release hotfixes as needed. Please [report any issues that you find](https://github.com/PaperMC/adventure/issues/new) and reach out for help in the [#adventure-help channel](https://discord.com/channels/289587909051416579/1342377752774443008) of the [PaperMC Discord](https://discord.com/invite/PaperMC) if you need to. Please read the [migration information on the Adventure documentation](https://docs.papermc.io/adventure/migration/adventure-4.x/) for full information about the changes made in this update and notes about migrating from the 4.x series to 5.x. For development information about the 5.0 update, check out the following links: * [Adventure 5.0 info issue](https://github.com/PaperMC/adventure/issues/1202) * [Adventure 5.0 PR](https://github.com/PaperMC/adventure/pull/1253) What's Changed -------------- There are also some additional features and fixes unrelated to the major breaking changes introduced in 5.0.0. These are documented below. ### ✨ Features * Add BookLike interface by [@kezz](https://github.com/kezz) in [#1346](https://github.com/PaperMC/adventure/pull/1346) * Minecraft 26.1 update changes by [@kezz](https://github.com/kezz) in [#1390](https://github.com/PaperMC/adventure/pull/1390) * [MiniMessage presets system](https://docs.papermc.io/adventure/minimessage/api/#presets) by [@kezz](https://github.com/kezz) in [#1388](https://github.com/PaperMC/adventure/pull/1388) * Add femboy flag to pride tag by [@RabbitTV22](https://github.com/RabbitTV22) in [#1357](https://github.com/PaperMC/adventure/pull/1357) ### 🐛 Fixes * Support all UUID versions in head tag by [@Emilxyz](https://github.com/Emilxyz) in [#1375](https://github.com/PaperMC/adventure/pull/1375) New Contributors ---------------- * [@RabbitTV22](https://github.com/RabbitTV22) made their first contribution in [#1357](https://github.com/PaperMC/adventure/pull/1357) * [@Privatech38](https://github.com/Privatech38) made their first contribution in [#1373](https://github.com/PaperMC/adventure/pull/1373) Thanks to everyone who helped out along the way with the 5.0.0 update, and special thanks to the following for their hard work on the update: * [@kezz](https://github.com/kezz) * [@zml2008](https://github.com/zml2008) * [@Strokkur424](https://github.com/Strokkur424) **Full Changelog**: [v4.26.1...v5.0.0](https://github.com/PaperMC/adventure/compare/v4.26.1...v5.0.0) * * * 🌏 Adventure 4.26.1 ------------------- [Section titled “🌏 Adventure 4.26.1”](https://docs.papermc.io/adventure/version-history/adventure/#v4.26.1) Released on Apr 16, 2026 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v4.26.1) Adventure 4.26.1 is _hopefully_ the final release before the full release of 5.0. This release solely contains final changes and deprecations in preparation of the 5.0. For full information about the 5.0 update, check out the following links: * [Adventure 5.0 info issue](https://github.com/PaperMC/adventure/issues/1202) * [Adventure 5.0 PR](https://github.com/PaperMC/adventure/pull/1253) * [Migration docs PR](https://github.com/PaperMC/docs/pull/678) Note: 4.26.0 was released on GitHub but never deployed and should be considered non existant. What's Changed -------------- ### ✨ Features * Pre-5.0 update changes/deprecations by [@kezz](https://github.com/kezz) in [#1329](https://github.com/PaperMC/adventure/pull/1329) ### 📚 Documentation * docs: Update documentation, discord and snapshot links by [@kezz](https://github.com/kezz) in [#1323](https://github.com/PaperMC/adventure/pull/1323) **Full Changelog**: [v4.25.0...v4.26.1](https://github.com/PaperMC/adventure/compare/v4.25.0...v4.26.1) * * * 🌏 Adventure 4.26.0 ------------------- [Section titled “🌏 Adventure 4.26.0”](https://docs.papermc.io/adventure/version-history/adventure/#v4.26.0) Released on Apr 16, 2026 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v4.26.0) Adventure 4.26.0 is _hopefully_ the final release before the full release of 5.0. This release solely contains final changes and deprecations in preparation of the 5.0. For full information about the 5.0 update, check out the following links: * [Adventure 5.0 info issue](https://github.com/PaperMC/adventure/issues/1202) * [Adventure 5.0 PR](https://github.com/PaperMC/adventure/pull/1253) * [Migration docs PR](https://github.com/PaperMC/docs/pull/678) What's Changed -------------- ### ✨ Features * Pre-5.0 update changes/deprecations by [@kezz](https://github.com/kezz) in [#1329](https://github.com/PaperMC/adventure/pull/1329) ### 📚 Documentation * docs: Update documentation, discord and snapshot links by [@kezz](https://github.com/kezz) in [#1323](https://github.com/PaperMC/adventure/pull/1323) **Full Changelog**: [v4.25.0...v4.26.0](https://github.com/PaperMC/adventure/compare/v4.25.0...v4.26.0) * * * 🌏 Adventure 4.25.0 ------------------- [Section titled “🌏 Adventure 4.25.0”](https://docs.papermc.io/adventure/version-history/adventure/#v4.25.0) Released on Apr 16, 2026 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v4.25.0) What's Changed -------------- ### ✨ Features * Update for 1.21.9 by [@jpenilla](https://github.com/jpenilla) in [#1291](https://github.com/PaperMC/adventure/pull/1291) * Add option to prepend https to click event urls by [@Emilxyz](https://github.com/Emilxyz) in [#1290](https://github.com/PaperMC/adventure/pull/1290) * Allow passing parentStyle to Component#compact by [@indyteo](https://github.com/indyteo) in [#1288](https://github.com/PaperMC/adventure/pull/1288) * Allow creation of a ClickEvent from an Action and Payload by [@Phoenix616](https://github.com/Phoenix616) in [#1322](https://github.com/PaperMC/adventure/pull/1322) * Add `CompoundBinaryTag` contains methods by [@tal5](https://github.com/tal5) in [#1265](https://github.com/PaperMC/adventure/pull/1265) * Add sequential (simple) head tag by [@Strokkur424](https://github.com/Strokkur424) in [#1320](https://github.com/PaperMC/adventure/pull/1320) * Allow creating builders with an initial capacity by [@tal5](https://github.com/tal5) in [#1264](https://github.com/PaperMC/adventure/pull/1264) * ObjectComponent serialization by [@Emilxyz](https://github.com/Emilxyz) in [#1293](https://github.com/PaperMC/adventure/pull/1293) ### 🐛 Fixes * Provide the property directly in the properties DefaultOverideProvider by [@kezz](https://github.com/kezz) in [#1279](https://github.com/PaperMC/adventure/pull/1279) * Correct `defaultValue` nullability by [@tal5](https://github.com/tal5) in [#1263](https://github.com/PaperMC/adventure/pull/1263) * Fix invalid url extraction in legacy component serializer by [@derklaro](https://github.com/derklaro) in [#1280](https://github.com/PaperMC/adventure/pull/1280) ### 📚 Documentation * Alongside this release, the old [adventure-docs](https://github.com/KyoriPowered/adventure-docs) repo has been archived and the documentation has been migrated to the [PaperMC docs](https://github.com/PaperMC/docs) repo. ### Other * Check TagResolver#has in more places by [@kezz](https://github.com/kezz) in [#1297](https://github.com/PaperMC/adventure/pull/1297) New Contributors ---------------- * [@tal5](https://github.com/tal5) made their first contribution in [#1263](https://github.com/PaperMC/adventure/pull/1263) * [@derklaro](https://github.com/derklaro) made their first contribution in [#1280](https://github.com/PaperMC/adventure/pull/1280) * [@indyteo](https://github.com/indyteo) made their first contribution in [#1288](https://github.com/PaperMC/adventure/pull/1288) * [@Phoenix616](https://github.com/Phoenix616) made their first contribution in [#1322](https://github.com/PaperMC/adventure/pull/1322) * [@Strokkur424](https://github.com/Strokkur424) made their first contribution in [#1291](https://github.com/PaperMC/adventure/pull/1291) **Full Changelog**: [v4.24.0...v4.25.0](https://github.com/PaperMC/adventure/compare/v4.24.0...v4.25.0) * * * 🌏 Adventure 4.24.0 ------------------- [Section titled “🌏 Adventure 4.24.0”](https://docs.papermc.io/adventure/version-history/adventure/#v4.24.0) Released on Jul 30, 2025 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v4.24.0) What's Changed -------------- ### ✨ Features * feature(api): Add a method to close an open dialog by [@kezz](https://github.com/kezz) in [#1246](https://github.com/PaperMC/adventure/pull/1246) * Implement #canTranslate in GlobalTranslatorImpl and call #canTranslate of its sources by [@ivi-kiwi](https://github.com/ivi-kiwi) in [#1252](https://github.com/PaperMC/adventure/pull/1252) * Add a less verbose way of creating titles by [@LaserSlime](https://github.com/LaserSlime) in [#1272](https://github.com/PaperMC/adventure/pull/1272) * feature(api): Property default override SPI and flattener nesting limit property by [@kezz](https://github.com/kezz) in [#1250](https://github.com/PaperMC/adventure/pull/1250) * Uppercase hex colors created by asHexColor to avoid item desyncs in Minecraft by [@MrPowerGamerBR](https://github.com/MrPowerGamerBR) in [#1277](https://github.com/PaperMC/adventure/pull/1277) ### 🐛 Fixes * Add `equals` to `VirtualComponent` by [@Seggan](https://github.com/Seggan) in [#1247](https://github.com/PaperMC/adventure/pull/1247) * fix: component flattener not popping styles in correct order by [@diogotcorreia](https://github.com/diogotcorreia) in [#1255](https://github.com/PaperMC/adventure/pull/1255) * fix(api): fix removing mutated source from GlobalTranslator by [@Emilxyz](https://github.com/Emilxyz) in [#1276](https://github.com/PaperMC/adventure/pull/1276) * Avoid interpreting the "byte" suffix as a binary radix by [@IllusionTheDev](https://github.com/IllusionTheDev) in [#1241](https://github.com/PaperMC/adventure/pull/1241) ### 📚 Documentation * docs: Remove wiki.vg link from NBT javadoc by [@kezz](https://github.com/kezz) in [#1251](https://github.com/PaperMC/adventure/pull/1251) ### Other * chore: Deprecate non-named UTF8ResourceBundleControl getter by [@kezz](https://github.com/kezz) in [00ebf2e](https://github.com/PaperMC/adventure/commit/00ebf2e198280bbff8bc56724c8d080018b597e6) New Contributors ---------------- * [@Seggan](https://github.com/Seggan) made their first contribution in [#1247](https://github.com/PaperMC/adventure/pull/1247) * [@diogotcorreia](https://github.com/diogotcorreia) made their first contribution in [#1255](https://github.com/PaperMC/adventure/pull/1255) * [@Emilxyz](https://github.com/Emilxyz) made their first contribution in [#1276](https://github.com/PaperMC/adventure/pull/1276) * [@ivi-kiwi](https://github.com/ivi-kiwi) made their first contribution in [#1252](https://github.com/PaperMC/adventure/pull/1252) * [@LaserSlime](https://github.com/LaserSlime) made their first contribution in [#1272](https://github.com/PaperMC/adventure/pull/1272) * [@IllusionTheDev](https://github.com/IllusionTheDev) made their first contribution in [#1241](https://github.com/PaperMC/adventure/pull/1241) * [@MrPowerGamerBR](https://github.com/MrPowerGamerBR) made their first contribution in [#1277](https://github.com/PaperMC/adventure/pull/1277) **Full Changelog**: [v4.23.0...v4.24.0](https://github.com/PaperMC/adventure/compare/v4.23.0...v4.24.0) * * * 🌏 Adventure 4.23.0 ------------------- [Section titled “🌏 Adventure 4.23.0”](https://docs.papermc.io/adventure/version-history/adventure/#v4.23.0) Released on Jun 18, 2025 - [GitHub](https://github.com/PaperMC/adventure/releases/tag/v4.23.0) This is a hotfix release to resolve some issues in the recently released v4.22.0. What's Changed -------------- ### 🐛 Fixes * fix: Ensure TagStringIO accepts hetergeneous lists in all reader methods by [@kezz](https://github.com/kezz) in [#1244](https://github.com/PaperMC/adventure/pull/1244) * fix: Make custom click events hold NBT payloads by [@kezz](https://github.com/kezz) in [#1243](https://github.com/PaperMC/adventure/pull/1243) * fix(key): Ensure keys with invalid namespaces throw the correct exception by [@kezz](https://github.com/kezz) in [#1245](https://github.com/PaperMC/adventure/pull/1245) **Full Changelog**: [v4.22.0...v4.23.0](https://github.com/PaperMC/adventure/compare/v4.22.0...v4.23.0) * * * Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Text (Chat Components) | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/text/#_top) Text (Chat Components) ====================== Components represent Minecraft chat components. Creating components ------------------- [Section titled “Creating components”](https://docs.papermc.io/adventure/text/#creating-components) // Creates a line of text saying "You're a Bunny! Press to jump!", with some coloring and styling.final TextComponent textComponent = Component.text("You're a ") .color(TextColor.color(0x443344)) .append(Component.text("Bunny", NamedTextColor.LIGHT_PURPLE)) .append(Component.text("! Press ")) .append( Component.keybind("key.jump") .color(NamedTextColor.LIGHT_PURPLE) .decoration(TextDecoration.BOLD, true) ) .append(Component.text(" to jump!"));// now you can send `textComponent` to something, such as a client You can also use a builder, which is mutable, and creates one final component with the children. // Creates a line of text saying "You're a Bunny! Press to jump!", with some coloring and styling.final TextComponent textComponent2 = Component.text() .content("You're a ") .color(TextColor.color(0x443344)) .append(Component.text().content("Bunny").color(NamedTextColor.LIGHT_PURPLE)) .append(Component.text("! Press ")) .append( Component.keybind().keybind("key.jump") .color(NamedTextColor.LIGHT_PURPLE) .decoration(TextDecoration.BOLD, true) .build() ) .append(Component.text(" to jump!")) .build();// now you can send `textComponent2` to something, such as a client Styling components ------------------ [Section titled “Styling components”](https://docs.papermc.io/adventure/text/#styling-components) Styles are a superset of TextColor and TextDecoration and can be applied to text components. TextColor represents any color in the RGB spectrum. You can also use NamedTextColor to choose from the default color palette. The following TextDecorations are available: * _Italic_ * **Bold** * Strikethrough * Underlined * Obfuscated Events ------ [Section titled “Events”](https://docs.papermc.io/adventure/text/#events) There are currently two types of events available for text components. Hover events allow you to show another component, item or entity when a user hovers their mouse over the text. When a user clicks on the text component, a click event is fired which can perform one of the following actions: * Open a URL * Open a file * Run a command * Suggest a command * Change a book’s page * Copy a string to clipboard * Open a dialog * Send a custom payload back to the server Serializing and deserializing components ---------------------------------------- [Section titled “Serializing and deserializing components”](https://docs.papermc.io/adventure/text/#serializing-and-deserializing-components) Serialization to JSON, legacy, and plain representations is also supported. Components can be serialized with [Text Serializers](https://docs.papermc.io/adventure/serializer) . Using components within your application ---------------------------------------- [Section titled “Using components within your application”](https://docs.papermc.io/adventure/text/#using-components-within-your-application) The way you use components within your application will of course vary depending on what you’re aiming to achieve. However, the most common task is likely to be sending a component to some sort of Minecraft client. The method for doing this will depend on the platform your program is running on, however it is likely to involve serializing the component to Minecraft’s JSON format, and then sending the JSON through another method provided by the platform. The text library is platform-agnostic and therefore doesn’t provide any way to send components to clients. Some platforms implement [Adventure natively](https://docs.papermc.io/adventure/platform/native) , so `Components` can be directly used with their API. For other platforms (Spigot/Bukkit, BungeeCord, and SpongeAPI 7), we provide compatibility bridges as [Platforms](https://docs.papermc.io/adventure/platform) which can be distributed with your own plugins. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Text serializers | PaperMC Docs [Skip to content](https://docs.papermc.io/adventure/serializer/#_top) Text serializers ================ The lowest-level way to convert between Adventure’s data and other formats are serializers. Some serializers convert to standard formats, while others convert to Adventure’s own formats. * [JSON](https://docs.papermc.io/adventure/serializer/json) * [Gson](https://docs.papermc.io/adventure/serializer/gson) * [Legacy](https://docs.papermc.io/adventure/serializer/legacy) * [Plain](https://docs.papermc.io/adventure/serializer/plain) * [MiniMessage](https://docs.papermc.io/adventure/minimessage) Components can be converted using any of these serializers: // Creates a text componentfinal TextComponent textComponent = Component.text() .content("Hello ") .color(NamedTextColor.GOLD) .append(Component.text("world", NamedTextColor.AQUA, TextDecoration.BOLD)) .append(Component.text("!", NamedTextColor.RED)) .build(); // Converts textComponent to the JSON form used for serialization by Minecraft.final String json = JSONComponentSerializer.json().serialize(textComponent); // Converts textComponent to a legacy string - "&6Hello &b&lworld&c!"final String legacy = LegacyComponentSerializer.legacyAmpersand().serialize(textComponent); // Converts textComponent to a plain string - "Hello world!"final String plain = PlainTextComponentSerializer.plainText().serialize(textComponent); The same is of course also possible in reverse for deserialization. // Converts JSON in the form used for serialization by Minecraft to a Componentfinal Component component = JSONComponentSerializer.json().deserialize(json); // Converts a legacy string (using formatting codes) to a TextComponentfinal Component component = LegacyComponentSerializer.legacyAmpersand().deserialize("&6Hello &b&lworld&c!"); // Converts a plain string to a TextComponentfinal Component component = PlainTextComponentSerializer.plainText().deserialize("Hello world!"); Text encoders ------------- [Section titled “Text encoders”](https://docs.papermc.io/adventure/serializer/#text-encoders) Text encoders are similar to serializers, but they only provide one-way operations, allowing for serialization but not deserialization. * [ANSI](https://docs.papermc.io/adventure/serializer/ansi) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Libraries used | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/credits/#_top) Libraries used ============== Velocity uses a number of open-source libraries: | Name | Author | License | | --- | --- | --- | | [Guava](https://github.com/google/guava) | [Google](https://github.com/google) | [Apache License 2.0](https://github.com/google/guava/blob/master/LICENSE) | | [Gson](https://github.com/google/gson) | [Google](https://github.com/google) | [Apache License 2.0](https://github.com/google/gson/blob/master/LICENSE) | | [Netty](https://github.com/netty/netty) | [Netty Project](https://netty.io/) | [Apache License 2.0](https://github.com/netty/netty/blob/4.1/LICENSE.txt) | | [libdeflate](https://github.com/ebiggers/libdeflate) | [Eric Biggers](https://github.com/ebiggers) | [MIT License](https://github.com/ebiggers/libdeflate/blob/master/COPYING) | | [adventure](https://github.com/PaperMC/adventure) | [PaperMC](https://github.com/PaperMC) | [MIT License](https://github.com/PaperMC/adventure/blob/main/4/license.txt) | | [Brigadier](https://github.com/Mojang/brigadier) | [Mojang](https://www.minecraft.net/) | [MIT License](https://github.com/Mojang/brigadier/blob/master/LICENSE) | | [event](https://github.com/KyoriPowered/event) | [KyoriPowered](https://github.com/KyoriPowered) | [MIT License](https://github.com/KyoriPowered/event/blob/master/license.txt) | | [ASM](https://asm.ow2.io/) | [OW2](https://asm.ow2.io/) | [BSD 3-Clause License](https://asm.ow2.io/license.html) | | [SLF4J](https://github.com/qos-ch/slf4j) | [SLF4J](https://www.slf4j.org/) | [MIT License](https://github.com/qos-ch/slf4j/blob/master/LICENSE.txt) | | [Log4j](https://logging.apache.org/log4j/2.x/) | [Log4j Team](https://logging.apache.org/log4j/2.3.x/log4j-web/team-list) | [Apache License 2.0](https://logging.apache.org/log4j/2.12.x/license.html) | | [TerminalConsoleAppender](https://github.com/Minecrell/TerminalConsoleAppender) | [Minecrell](https://github.com/Minecrell) | [MIT License](https://github.com/Minecrell/TerminalConsoleAppender/blob/master/LICENSE) | | [Configurate](https://github.com/SpongePowered/configurate) | [SpongePowered](https://github.com/SpongePowered) | [Apache License 2.0](https://github.com/SpongePowered/configurate/blob/master/LICENSE) | | [SnakeYAML](https://bitbucket.org/snakeyaml/snakeyaml) | [SnakeYAML](https://bitbucket.org/snakeyaml) | [Apache License 2.0](https://bitbucket.org/snakeyaml/snakeyaml/src/master/LICENSE.txt) | | [HOCON](https://github.com/lightbend/config) | [lightbend](https://github.com/lightbend) | [Apache License 2.0](https://github.com/lightbend/config/blob/master/LICENSE-2.0.txt) | | [toml4j](https://github.com/mwanji/toml4j) | [Moandji Ezana](https://github.com/mwanji) | [MIT License](https://github.com/mwanji/toml4j/blob/master/LICENSE) | | [Night-Config](https://github.com/TheElectronWill/night-config) | [TheElectronWill](https://github.com/TheElectronWill) | [GNU Lesser General Public License 3.0](https://github.com/TheElectronWill/night-config/blob/master/LICENSE) | | [fastutil](https://fastutil.di.unimi.it/) | [Sebastiano Vigna](https://vigna.di.unimi.it/) | [Apache License 2.0](https://github.com/vigna/fastutil/blob/master/LICENSE-2.0) | | [JLine](https://github.com/jline/jline3/blob/master/LICENSE.txt) | [JLine project](https://github.com/jline/jline3) | [BSD 3-Clause License](https://github.com/jline/jline3/blob/master/LICENSE.txt) | | [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client) | [Stephane Landelle](https://github.com/slandelle) | [Apache License 2.0](https://github.com/AsyncHttpClient/async-http-client/blob/master/LICENSE.txt) | | [completable-futures](https://github.com/spotify/completable-futures) | [Spotify](https://github.com/spotify) | [Apache License 2.0](https://github.com/spotify/completable-futures/blob/master/LICENSE) | Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Comparing with other proxies | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/comparisons-to-other-proxies/#_top) Comparing with other proxies ============================ Presumably, you have learned about what Velocity can do for you. But how does it stack up against other solutions out there? We’re trying to convince you to use Velocity, after all, so this document may be somewhat biased in our favor. Overview -------- [Section titled “Overview”](https://docs.papermc.io/velocity/comparisons-to-other-proxies/#overview) This is a quick overview of the differences between Velocity and other popular proxy software. Read below for more details. | Feature | BungeeCord | Waterfall | Velocity | | --- | --- | --- | --- | | Resource efficient | ❌ | ✅ | ✅✅ | | Velocity plugins | ❌ | ❌ | ✅ | | BungeeCord plugins | ✅ | ✅ | 🟨\* | | Secure player information forwarding | ❌ | ❌ | ✅ | | API supporting modern Minecraft features | ❌ | ❌ | ✅ | | Actively developed | ❓ | ❌ | ✅ | | Improved mod support | ❌ | ❌ | ✅\*\* | \* _The Velocity API does not support plugins made for BungeeCord/Waterfall, but [Snap](https://hangar.papermc.io/Phoenix616/Snap) can be installed for experimental support. Snap is not maintained by, or affiliated with, the Velocity project._ \*\* _Full Forge support for 1.7 through 1.12.2 and 1.20.2 or higher._ BungeeCord and derivatives -------------------------- [Section titled “BungeeCord and derivatives”](https://docs.papermc.io/velocity/comparisons-to-other-proxies/#bungeecord-and-derivatives) We can’t discuss the full history of Minecraft proxy software deeply – we recommend [Me4502’s excellent article](https://madelinemiller.dev/blog/decade-of-minecraft-multiplayer/) that covers the multiplayer Minecraft world in great detail. ### BungeeCord [Section titled “BungeeCord”](https://docs.papermc.io/velocity/comparisons-to-other-proxies/#bungeecord) The original author of Velocity, at the time of starting the project, had over 5 years of experience using BungeeCord, and knew its various quirks inside and out. There are several reasons why improving BungeeCord was a fool’s game: * BungeeCord is very conservative with regard to API changes. If it breaks some plugin developed 5 years ago from an inactive developer, you can forget about it. * The changes that _do_ change the API are often quite particular and niche use cases and changing the API in substantial ways is frowned upon (witness the support for RGB colors in `ChatColor`). * The project is essentially run like a cathedral. In BungeeCord (and its sister project, Spigot), the word of md\_5 is king. Contributing a simple security fix to BungeeCord earned the primary developer of Velocity at least two beratings from md\_5. * BungeeCord is actively hostile to continued support for Minecraft modding. * We have seen new modding APIs for _Minecraft_ since the first version of BungeeCord released in 2012. It’s time for a new and improved API that does not make the mistakes the BungeeCord API makes, and to draw influence from the new modding APIs that Minecraft now boasts. ### Waterfall [Section titled “Waterfall”](https://docs.papermc.io/velocity/comparisons-to-other-proxies/#waterfall) Partly due to experience obtained by the author’s own experience with BungeeCord, he founded the Waterfall project in 2016 as a fork of BungeeCord, modeled after Paper, with the explicit aim of improving BungeeCord. _We tried the obvious next step_. Meet [Hyrum’s Law](https://www.hyrumslaw.com/) : > With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody. Here’s Hyrum’s law in comic format, in case that eases getting the point across: > [![xkcd #1172](https://imgs.xkcd.com/comics/workflow.png)](https://xkcd.com/1172/) > > [“Workflow”](https://xkcd.com/1172/) > from [xkcd](https://xkcd.com/) > by Randal Munroe, [licensed](https://xkcd.com/license.html) > under [CC BY-NC 2.5](https://creativecommons.org/licenses/by-nc/2.5/) Most BungeeCord plugins are deeply dependent on the specific behaviors and quirks BungeeCord exposes, which Velocity cannot perfectly emulate. As a result, the number of changes one can make to BungeeCord and have plugins retain the same behavior is minimal. Suppose you have played a video game published by Company A. It runs on an operating system made by Company B. One day, Company B releases a new version of their operating system, and you upgrade to it, only to recoil in horror as that video game no longer works. (Worse, Studio A might be out of business at that point, so no patch is forthcoming.) Who do you blame, Company A for producing a defective product, or Company B for breaking the game? [This isn’t a hypothetical](https://devblogs.microsoft.com/oldnewthing/20110131-00/?p=11633) . We can point to one example where [an attempt](https://github.com/PaperMC/Waterfall/commit/c8eb6aec7bac82fd309fa6d6113b8a0418317b01) to improve scoreboard handling on 1.13 and above [was reversed](https://github.com/PaperMC/Waterfall/issues/255) thanks to plugins expecting BungeeCord’s broken behavior. At this point, it is fairly obvious why making a clean break was better. Given that this happened near the start of the Velocity project’s lifetime, it was probably a quite powerful motivator, although it certainly wasn’t the only motivator. ### Hypothetical BungeeCord API-based Velocity [Section titled “Hypothetical BungeeCord API-based Velocity”](https://docs.papermc.io/velocity/comparisons-to-other-proxies/#hypothetical-bungeecord-api-based-velocity) We are compelled to mention this briefly as this was a topic brought up in the early days of the project. We could have based Velocity on the BungeeCord API (or a derivative thereof, such as the Waterfall API) instead. This has the same problems as Waterfall, perhaps more as we would need to emulate _all_ the behavior of the BungeeCord API independently. The Wine project has been trying for over 3 decades to provide a shim layer that allows Windows programs to run on Linux and other operating systems. Their efforts remain ongoing to this day. It is hard to emulate the behavior of another operating system’s environment. The authors of ReactOS have it even worse, trying to emulate all the quirks of Windows, including its kernel, and they have set their baseline to a version of Windows that was released 2 decades ago. Their work is even further from completed than Wine’s is. We would have to spend a lot of time pretending that Velocity looked and quacked just like BungeeCord. We intentionally rejected this approach. It’s not worth doing. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # How-to guides | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/admin/how-to/#_top) How-to guides ============= How-to guides for setting up specific features of Velocity and managing the proxy. [Tuning Velocity](https://docs.papermc.io/velocity/tuning) How to tune Velocity to allow for even better performance. [Securing your servers](https://docs.papermc.io/velocity/security) An explanation of how to secure your servers. [Migration guide](https://docs.papermc.io/velocity/migration) How to migrate your proxy between different Velocity versions. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Built-in commands | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/built-in-commands/#_top) Built-in commands ================= Velocity includes a few commands in the core of the proxy by default. These commands were chosen based on how generally useful they are to most users. Of course, you can always install plugins to add more commands if you want. `/velocity` ----------- [Section titled “/velocity”](https://docs.papermc.io/velocity/built-in-commands/#velocity) The `/velocity` command contains a number of subcommands to manage the proxy. ### `/velocity plugins` [Section titled “/velocity plugins”](https://docs.papermc.io/velocity/built-in-commands/#velocity-plugins) If the user has the `velocity.command.plugins` permission, they can view all the plugins currently active on the proxy using `/velocity plugins`, including the name, authors, and version. ### `/velocity info` [Section titled “/velocity info”](https://docs.papermc.io/velocity/built-in-commands/#velocity-info) If the user has the `velocity.command.info` permission, they can view information about the Velocity instance, such as the version of Velocity running on the proxy. ### `/velocity reload` [Section titled “/velocity reload”](https://docs.papermc.io/velocity/built-in-commands/#velocity-reload) If the user has the `velocity.command.reload` permission, the proxy will read and reconfigure itself from the `velocity.toml` on disk. If there are problems with parsing the file, no changes will be applied. ### `/velocity dump` [Section titled “/velocity dump”](https://docs.papermc.io/velocity/built-in-commands/#velocity-dump) If the user has the `velocity.command.dump` permission, they can use this command to get an anonymized dump of details on the proxy. This can be sent to the PaperMC Discord to help us provide support. ### `/velocity heap` [Section titled “/velocity heap”](https://docs.papermc.io/velocity/built-in-commands/#velocity-heap) If the user has the `velocity.command.heap` permission, they will be able to generate a heap dump from the running Velocity instance, which will allow a detailed analysis of memory consumption. The generated heap dump will be found in the `dumps` folder. `/server` --------- [Section titled “/server”](https://docs.papermc.io/velocity/built-in-commands/#server) If the user has the `velocity.command.server` permission (by default, this is granted to all users), players can use this command to view and switch to another server. Executing just `/server` will send the user the name of the server they are currently on, along with options to move to other servers configured on the proxy. If a server name has been provided, Velocity will attempt to connect to the server. `/shutdown` ----------- [Section titled “/shutdown”](https://docs.papermc.io/velocity/built-in-commands/#shutdown) When run, this will gracefully shut down the Velocity proxy. All players will be disconnected from the proxy, and plugins will have a chance to finish up before the proxy shuts down. An optional reason can be given, either as JSON or with [MiniMessage Format](https://docs.papermc.io/adventure/minimessage/format/) . If the provided message starts with `"`, `[`, or `{`, then the message is attempted to be parsed as JSON. If this parsing fails, or the message starts with anything else, the message will be parsed as MiniMessage.\ \ `/glist`\ --------\ \ [Section titled “/glist”](https://docs.papermc.io/velocity/built-in-commands/#glist)\ \ If the user has the `velocity.command.glist` permission (by default, this is granted to nobody), players can use this command to view the number of players currently on the proxy and use `/glist all` to get a listing of players per server.\ \ `/send`\ -------\ \ [Section titled “/send”](https://docs.papermc.io/velocity/built-in-commands/#send)\ \ If the user has the `velocity.command.send` permission, they can send other players (or all players on the proxy) to another server.\ \ Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/)\ .\ \ This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Getting started | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/admin/getting-started/#_top) Getting started =============== Guides for getting started with running a Velocity proxy. [Getting started](https://docs.papermc.io/velocity/getting-started) How to install and set up a minimal configuration of Velocity. [What does Velocity do for me?](https://docs.papermc.io/velocity/why-velocity) An explanation for why you should run Velocity. [Configuring player information forwarding](https://docs.papermc.io/velocity/player-information-forwarding) How to configure information forwarding on Velocity. [Frequently asked questions](https://docs.papermc.io/velocity/faq) Frequently asked Velocity administration questions. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Migration guide | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/migration/#_top) Migration guide =============== New to Velocity, or upgrading to a new version of Velocity? This page will briefly explore what you need to be aware of for a successful migration. Migrating from Velocity 1.0.x to Velocity 1.1.0 ----------------------------------------------- [Section titled “Migrating from Velocity 1.0.x to Velocity 1.1.0”](https://docs.papermc.io/velocity/migration/#migrating-from-velocity-10x-to-velocity-110) Moving from Velocity 1.0.x to Velocity 1.1.0 should be as simple as just replacing the Velocity JAR and restarting the proxy. You may want to back up your `velocity.toml` and then delete the current `velocity.toml` and let Velocity regenerate it to add the new settings that Velocity 1.1.0 introduces. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Velocity Documentation | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/#_top) Velocity Documentation ====================== Velocity is the ridiculously scalable, flexible Minecraft proxy. Getting started --------------- [Section titled “Getting started”](https://docs.papermc.io/velocity/#getting-started) It is simple to get started with Velocity. Get started with our [Getting Started guide](https://docs.papermc.io/velocity/getting-started) . I need help ----------- [Section titled “I need help”](https://docs.papermc.io/velocity/#i-need-help) If you need some help with Velocity, please seek help in the following places: ### 📖 These Docs [Section titled “📖 These Docs”](https://docs.papermc.io/velocity/#-these-docs) We have put a lot of effort into documenting Velocity as much as possible with our new website and our coverage will continue to expand. We strongly encourage you to check the sidebar of the docs for relevant resources. Helping yourself using the resources in these docs saves all of us time. We recommend you visit the [frequently asked questions](https://docs.papermc.io/velocity/faq) to begin your search. Most common issues with Velocity are answered there. Please do not be offended if we respond to your question linking back here. Asking us a question already answered in the documentation doesn’t help anyone. ### 💬 Our Discord [Section titled “💬 Our Discord”](https://docs.papermc.io/velocity/#-our-discord) If you have searched the docs and didn’t find the answer to your question, then it is time to [join our Discord](https://discord.gg/papermc) to ask your question. [Administration](https://docs.papermc.io/velocity/admin) Information and tutorials regarding the administration of a Velocity proxy. [Development](https://docs.papermc.io/velocity/dev) Information and tutorials for developers on how to create and expand on Velocity plugins. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Configuring Velocity | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/configuration/#_top) Configuring Velocity ==================== Velocity is designed to be easy to configure and set up. Every Velocity file is stored in `velocity.toml`, located in the directory where you started the proxy. Velocity uses the [TOML](https://github.com/toml-lang/toml) file format, as it is easy to understand and avoids pitfalls of YAML and other configuration formats common in the community. An up-to-date version of the default configuration can be found on [GitHub](https://github.com/PaperMC/Velocity/blob/dev/3.0.0/proxy/src/main/resources/default-velocity.toml) . Data types ---------- [Section titled “Data types”](https://docs.papermc.io/velocity/configuration/#data-types) There are a few “special” data types in the Velocity configuration. ### Chat [Section titled “Chat”](https://docs.papermc.io/velocity/configuration/#chat) Chat messages may be provided in [MiniMessage](https://docs.papermc.io/adventure/minimessage/format/) format. RGB support is available for Minecraft 1.16 and later versions. ### Address [Section titled “Address”](https://docs.papermc.io/velocity/configuration/#address) An address is a pairing of an IP address or hostname, and a port, separated by a colon (`:`). For instance, `127.0.0.1:25577` and `server01.example.com:25565` are valid addresses. Root section ------------ [Section titled “Root section”](https://docs.papermc.io/velocity/configuration/#root-section) These settings mostly cover the basic, most essential settings of the proxy. | Setting Name | Type | Description | | --- | --- | --- | | `config-version` | String | This is the current config version used by Velocity. You should not alter this setting. | | `bind` | Address | This tells the proxy to accept connections on a specific IP. By default, Velocity will listen for connections on all IP addresses on the computer on port 25565. | | `motd` | Chat | This allows you to change the message shown to players when they add your server to their server list. You can use [MiniMessage format](https://docs.papermc.io/adventure/minimessage/format/)
. | | `show-max-players` | Integer | This allows you to customize the number of “maximum” players in the player’s server list. Note that Velocity doesn’t have a maximum number of players it supports. | | `online-mode` | Boolean | Should we authenticate players with Mojang? By default, this is on. | | `force-key-authentication` | Boolean | Should the proxy enforce the new public key security standard? By default, this is on. | | `player-info-forwarding-mode` | Enum | See [Configuring player information forwarding](https://docs.papermc.io/velocity/player-information-forwarding)
for more information. | | `prevent-client-proxy-connections` | Boolean | If client’s ISP/AS sent from this proxy is different from the one from Mojang’s authentication server, the player is kicked. This disallows some VPN and proxy connections but is a weak form of protection. | | `forwarding-secret-file` | String | The name of the file in which the forwarding secret is stored. This secret is used to ensure that player info forwarded by Velocity comes from your proxy and not from someone pretending to run Velocity. See the “Player info forwarding” section for more info. | | `announce-forge` | Boolean | This setting determines whether Velocity should present itself as a Forge/FML-compatible server. By default, this is disabled. | | `kick-existing-players` | Boolean | Allows restoring the Vanilla behavior of kicking users on the proxy if they try to reconnect (e.g. lost internet connection briefly). | | `ping-passthrough` | String | Allows forwarding nothing (the default), the `MODS` (for Forge), the `DESCRIPTION`, or everything (`ALL`) from the `try` list (or forced host server connection order). | | `enable-player-address-logging` | Boolean | If disabled (default is true), player IP addresses will be replaced by `` in logs. | `servers` section ----------------- [Section titled “servers section”](https://docs.papermc.io/velocity/configuration/#servers-section) | Setting Name | Type | Description | | --- | --- | --- | | A server name | Address | This makes the proxy aware of a server that it can connect to. | | `try` | Array | This specifies what servers Velocity should try to connect to upon player login and when a player is kicked from a server. | `forced-hosts` section ---------------------- [Section titled “forced-hosts section”](https://docs.papermc.io/velocity/configuration/#forced-hosts-section) | Setting Name | Type | Description | | --- | --- | --- | | A host name | Hostname | This configures the proxy to create a forced host for the specified hostname. An array of servers to try for the specified hostname is the value. | `advanced` section ------------------ [Section titled “advanced section”](https://docs.papermc.io/velocity/configuration/#advanced-section) | Setting name | Type | Description | | --- | --- | --- | | `compression-threshold` | Integer | This is the minimum size (in bytes) that a packet must be before the proxy compresses it. Minecraft uses 256 bytes by default. | | `compression-level` | Integer | This setting indicates what `zlib` compression level the proxy should use to compress packets. The default value uses the default zlib level. | | `login-ratelimit` | Integer | This setting determines the minimum amount of time (in milliseconds) that must pass before a connection from the same IP address will be accepted by the proxy. A value of `0` disables the rate limit. | | `connection-timeout` | Integer | This setting determines how long the proxy will wait to connect to a server before timing out. | | `read-timeout` | Integer | This setting determines how long the proxy will wait to receive data from the server before timing out. | | `haproxy-protocol` | Boolean | This setting determines whether or not Velocity should receive HAProxy PROXY messages. If you don’t use HAProxy, leave this setting off. | | `tcp-fast-open` | Boolean | This setting allows you to enable TCP Fast Open support in Velocity. Your proxy must run on Linux kernel >=4.14 for this setting to apply. | | `bungee-plugin-message-channel` | Boolean | This setting allows you to enable or disable support for the BungeeCord plugin messaging channel. | | `show-ping-requests` | Boolean | This setting allows you to log ping requests sent by clients to the proxy. | | `announce-proxy-commands` | Boolean | This setting allows you to enable or disable explicitly sending proxy commands to the client (for Minecraft 1.13+ tab completion). | | `failover-on-unexpected-server-disconnect` | Boolean | This setting allows you to determine if the proxy should failover or disconnect the user in the event of an unclean disconnect. | | `log-command-executions` | Boolean | Determines whether or not the proxy should log all commands run by the user. | | `log-player-connections` | Boolean | Enables logging of player connections when connecting to the proxy, switching servers and disconnecting from the proxy. | | `accepts-transfers` | Boolean | Determines whether or not the proxy accepts incoming transfers from other servers. If disabled, the proxy will disconnect transferred clients. | | `enable-reuse-port` | Boolean | Enables support for SO\_REUSEPORT. This may help the proxy scale better on multicore systems with a lot of incoming connections, and provide better CPU utilization than the existing strategy of having a single thread accepting connections and distributing them to worker threads. Requires Linux or macOS. | | `command-rate-limit` | Integer | How fast (in milliseconds) are clients allowed to send commands after the last command. By default this is 50ms (20 commands per second) | | `forward-commands-if-rate-limited` | Boolean | Should we forward commands to the backend upon being rate limited? This will forward the command to the server instead of processing it on the proxy. Since most server implementations have a rate limit, this will prevent the player from being able to send excessive commands to the server. | | `kick-after-rate-limited-commands` | Integer | How many commands are allowed to be sent after the rate limit is hit before the player is kicked? Setting this to 0 or lower will disable this feature. | | `tab-complete-rate-limit` | Integer | How fast (in milliseconds) are clients allowed to send tab completions after the last tab completion | | `kick-after-rate-limited-tab-completes` | Integer | How many tab completions are allowed to be sent after the rate limit is hit before the player is kicked? Setting this to 0 or lower will disable this feature. | `query` section --------------- [Section titled “query section”](https://docs.papermc.io/velocity/configuration/#query-section) | Setting name | Type | Description | | --- | --- | --- | | `enabled` | Boolean | Whether or not Velocity should reply to Minecraft query protocol requests. You can usually leave this false. | | `port` | Number | Specifies which port that Velocity should listen on for GameSpy 4 (Minecraft query protocol) requests. | | `map` | String | Specifies the map name to be shown to clients. | | `show-plugins` | Boolean | Whether or not Velocity plugins are included in the query responses. | Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # How-to guides | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/how-to/#_top) How-to guides ============= How-to guides for developing your Velocity plugin. [Dependency management](https://docs.papermc.io/velocity/dev/dependency-management) How to handle dependencies within your Velocity plugin. [Porting your plugin from Velocity 1.x.x](https://docs.papermc.io/velocity/dev/porting-plugins-from-velocity-1) How to port your plugin from Velocity 1.x.x to modern API. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Getting started | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/getting-started/#_top) Getting started =============== Guides for getting started with developing a Velocity plugin. [Creating your first plugin](https://docs.papermc.io/velocity/dev/creating-your-first-plugin) How to create your first plugin with the Velocity API. [Velocity plugin basics](https://docs.papermc.io/velocity/dev/api-basics) How to get started with the Velocity API. [Common pitfalls](https://docs.papermc.io/velocity/dev/pitfalls) How to avoid common pitfalls within Velocity. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Porting your plugin from Velocity 1.x.x | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/porting-plugins-from-velocity-1/#_top) Porting your plugin from Velocity 1.x.x ======================================= Velocity 3.0.0 includes important API changes from the Velocity 1.x.x series. **Please read this document very carefully**. Minimum supported Java version bump ----------------------------------- [Section titled “Minimum supported Java version bump”](https://docs.papermc.io/velocity/dev/porting-plugins-from-velocity-1/#minimum-supported-java-version-bump) Velocity 3.5.x and above now requires Java 21 and above. Removal of legacy dependencies ------------------------------ [Section titled “Removal of legacy dependencies”](https://docs.papermc.io/velocity/dev/porting-plugins-from-velocity-1/#removal-of-legacy-dependencies) We removed all support for the old `text` 3 library. For `text` 3.x.x (and all the APIs that depend on it), direct equivalents are available in [Adventure](https://docs.papermc.io/adventure/) , which was introduced in Velocity 1.1.0. `toml4j`, deprecated in Velocity 1.1.0 (as it is no longer maintained), has not been removed to provide more time for plugins to migrate to Configurate. However, you should prepare to either switch to Configurate or shade `toml4j` into your plugin directly. New asynchronous event system ----------------------------- [Section titled “New asynchronous event system”](https://docs.papermc.io/velocity/dev/porting-plugins-from-velocity-1/#new-asynchronous-event-system) Velocity 3.0.0 contains a backport of Velocity Polymer’s event system, which differs from Velocity 1.x.x’s event system in a number of ways. Velocity 1.x.x’s event model forced all events to be executed asynchronously on a fixed-size thread pool, which has proven over time to be a flawed model. Existing event handlers will continue to work unmodified on Velocity 3.0.0, as all event handlers are assumed to be asynchronous blocking handlers by default. However, there are some new APIs introduced for handling continuations - see the [event API page](https://docs.papermc.io/velocity/dev/event-api) for more information. However, you are encouraged to migrate your event listeners to the new event API paradigms. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Common pitfalls | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/pitfalls/#_top) Common pitfalls =============== While we try to make the API a pleasure to use, there are the occasional rough edges, and you should be aware of them. Accessing the API at construction time -------------------------------------- [Section titled “Accessing the API at construction time”](https://docs.papermc.io/velocity/dev/pitfalls/#accessing-the-api-at-construction-time) In Velocity, plugin loading is split into two steps: construction and initialization. The code in your plugin’s constructor is part of the construction phase. There is very little you can do safely during construction, especially as the API does not specify which operations are safe to run during construction. Notably, you can’t register an event listener in your constructor, because you need to have a valid plugin registration, but Velocity can’t register the plugin until the plugin has been constructed. To break this cycle, you should always wait for initialization, which is indicated when Velocity fires the [`ProxyInitializeEvent`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/proxy/ProxyInitializeEvent.html) . We can do things on initialization by adding a listener for this event, as shown below. Note that Velocity automatically registers your plugin main class as a listener. @Subscribepublic void onProxyInitialization(ProxyInitializeEvent event) { // Do some operation demanding access to the Velocity API here. // For instance, we could register an event: server.getEventManager().register(this, new PluginListener());} Audience operations are not fully supported ------------------------------------------- [Section titled “Audience operations are not fully supported”](https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported) Velocity currently does not support all Audience operations of the Adventure API, so these operations should be handled on the backend. Furthermore, playing sound was previously considered infeasible for versions below 1.19.3, a registry of hardcoded sound IDs is required. | Operation | Supported | | --- | --- | | Chat messages | Yes | | Action bar messages | Yes | | Titles | Yes | | Bossbars | Yes | | Tablist header and footer | Yes | | Resource packs | Yes | | Sounds | Yes[1](https://docs.papermc.io/velocity/dev/pitfalls/#user-content-fn-sounds-note) | | Books | No | | Dialogs | No | Footnotes --------- [Section titled “Footnotes”](https://docs.papermc.io/velocity/dev/pitfalls/#footnote-label) 1. Playing sounds only works on 1.19.3+ and requires an emitter ([`Sound.Emitter#self()`](https://jd.advntr.dev/api/latest/net/kyori/adventure/sound/Sound.Emitter.html#self()) or another player from the same server). [`Player#playSound(Sound)`](https://jd.papermc.io/velocity/com/velocitypowered/api/proxy/Player.html#playSound(net.kyori.adventure.sound.Sound)) is not implemented, as Adventure’s contract requires sounds to play at the player’s current position. [↩](https://docs.papermc.io/velocity/dev/pitfalls/#user-content-fnref-sounds-note) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Dependency management | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/dependency-management/#_top) Dependency management ===================== Dependencies are common. You need to hook into another plugin. You don’t want to write the same code someone else has already solved. Whatever you do, you need a way to manage your dependencies effectively. Plugin dependencies ------------------- [Section titled “Plugin dependencies”](https://docs.papermc.io/velocity/dev/dependency-management/#plugin-dependencies) Adding a dependency on another plugin is done with the [`@Plugin`](https://jd.papermc.io/velocity/com/velocitypowered/api/plugin/Plugin.html) annotation in your main class. Let’s revisit that briefly: @Plugin( id = "myfirstplugin", name = "My Plugin", version = "0.1.0")public class VelocityTest { // ...} Say we have a dependency on another plugin, call it `wonderplugin`. To add it as a dependency, do the following: @Plugin( id = "myfirstplugin", name = "My Plugin", version = "0.1.0", dependencies = { @Dependency(id = "wonderplugin") })public class VelocityTest { // ...} The id of the dependency is the same as the other plugin’s `id` from its `@Plugin` annotation. This is why having a stable plugin ID is important. That’s it! Now, your plugin will require `wonderplugin` to load, and when it does, it will load _after_ `wonderplugin`. To specify multiple dependencies, separate them by commas: `dependencies = {@Dependency(id = "wonderplugin"), @Dependency(id = "otherplugin")}` Optional plugin dependencies ---------------------------- [Section titled “Optional plugin dependencies”](https://docs.papermc.io/velocity/dev/dependency-management/#optional-plugin-dependencies) To make a dependency optional, add `optional = true`, like shown: @Plugin( id = "myfirstplugin", name = "My Plugin", version = "0.1.0", dependencies = { @Dependency(id = "wonderplugin", optional = true) })public class VelocityTest { // ...} External dependencies --------------------- [Section titled “External dependencies”](https://docs.papermc.io/velocity/dev/dependency-management/#external-dependencies) Dependencies on other libraries aren’t handled by Velocity. You will need to add them using your build system. If your plugin does not shade its dependencies, but rather attaches them from a directory, you may use the [`PluginManager`](https://jd.papermc.io/velocity/com/velocitypowered/api/plugin/PluginManager.html) ’s [`addToClasspath`](https://jd.papermc.io/velocity/com/velocitypowered/api/plugin/PluginManager.html#addToClasspath(java.lang.Object,java.nio.file.Path)) method instead of using reflection to access the [`ClassLoader`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/ClassLoader.html) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Securing your servers | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/security/#_top) Securing your servers ===================== It is vital that you secure your backend servers. As part of setting up Velocity, you will put your server into offline mode, which means in theory, someone could impersonate any player on your server. This is extremely dangerous, so it is important to make sure only the proxy can connect to your servers. This guide will explore the various options for securing your backend servers so only your proxy can connect to them. Note that this is an _exploration_ of options, aiming to review the various options and give you advantages and disadvantages to them, so you can make an informed decision. This list is not in any particular order, and almost all of these methods can be combined as needed. Operating system firewalls -------------------------- [Section titled “Operating system firewalls”](https://docs.papermc.io/velocity/security/#operating-system-firewalls) When properly configured, using the firewall facilities provided by your server’s operating system is a highly effective way to protect your servers. The Velocity project **strongly recommends the use of a firewall**. Instructions for your operating system may vary. Solutions for major server OSes include: * Windows: Windows Firewall * Linux: iptables, nftables **Advantages**: * Fool-proof if you do not give untrusted servers access to your servers * Does not require any extra Minecraft server configuration * Part of good system hardening advice for any operating system **Disadvantages**: * Tricky first-time setup * May be difficult to use with multiple proxies * Firewall configuration must be kept in sync with new servers and proxies * Not viable on a shared host Velocity modern forwarding -------------------------- [Section titled “Velocity modern forwarding”](https://docs.papermc.io/velocity/security/#velocity-modern-forwarding) If your server only supports Minecraft 1.13 and above, Velocity’s modern forwarding can forward player information to your servers and provide a second layer of protection against someone trying to impersonate as your proxy. **Advantages**: * Get player info forwarding for free * Secure on a shared host, provided the host has implemented proper protections * Works if you host your server on multiple physical servers **Disadvantages**: * Only works for Minecraft 1.13 and above * Requires Paper 1.13 or above, or FabricProxy-Lite if you use Fabric * Relies on the forwarding secret being kept secret Binding to `localhost` ---------------------- [Section titled “Binding to localhost”](https://docs.papermc.io/velocity/security/#binding-to-localhost) If you are hosting your proxy on the same physical computer as your other servers (and nobody else is hosting servers on them), binding your servers to `localhost` is a very simple way of protecting them from getting connected to by anything other than the proxy. For each server, open the `server.properties` file. Find the line that starts with `server-ip` and change the line to `server-ip=127.0.0.1`. Save the file and restart the server. Afterwards, open your `velocity.toml` file and ensure all the servers are pointing to `127.0.0.1:`. **Advantages**: * Trivial setup compared to other methods discussed * Fool-proof if you do not give untrusted users access to your server **Disadvantages**: * Setup must be reversed (and an alternate method used) if you move any of the servers to a different physical server ( such that the proxy and the server are not on the same physical server) * Not viable on a shared host Using an encrypted tunnel ------------------------- [Section titled “Using an encrypted tunnel”](https://docs.papermc.io/velocity/security/#using-an-encrypted-tunnel) This is a variation of binding to `localhost`, but instead of hosting all your servers on a single physical server, you will set up an encrypted tunnel between each of your servers, and make sure the server only listens for incoming connections from the tunnel. There are many different solutions, ranging from VPN solutions such as [WireGuard](https://www.wireguard.com/) , [OpenVPN](https://openvpn.net/) , and [tinc](https://www.tinc-vpn.org/) to encrypted tunnels such as [spiped](https://www.tarsnap.com/spiped.html) . This guide will not go into details of how to set up each of these solutions. **Advantages**: * Encrypts traffic between your proxy and your servers while ensuring only authorized clients can connect to your servers **Disadvantages**: * Very complex setup * Impossible to use on a shared host IP whitelisting plugins ----------------------- [Section titled “IP whitelisting plugins”](https://docs.papermc.io/velocity/security/#ip-whitelisting-plugins) As a last line of defense, you can choose to restrict logins to users on an IP whitelist using a plugin like [IPWhitelist](https://www.spigotmc.org/resources/ipwhitelist.61/) . **Advantages**: * May be your only solution if none of the other solutions will work (especially on a shared host) **Disadvantages**: * Vulnerable to attack if the attacker can get a server on the same node as your proxy is on Other important security advice ------------------------------- [Section titled “Other important security advice”](https://docs.papermc.io/velocity/security/#other-important-security-advice) This common-sense general advice goes without saying: * Keep frequent backups of your server * Set up a firewall on your server * Run your servers as an unprivileged user (this means no `sudo` access or running as `root` for Linux users!) * Update Velocity, your Minecraft server and server plugins, and your server’s operating system frequently * Use strong passwords * Carefully think about the potential impacts of installing any plugins or software before actually doing so * Secure any and all other services you may be running on your server * Follow all system hardening advice for your operating system We will not provide a full treatment to the advice given above, so please do some research of your own. Your setup will vary - there is no “one size fits all” advice we can give other than these general guidelines. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Server compatibility | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/server-compatibility/#_top) Server compatibility ==================== Velocity is compatible with many Minecraft server implementations. The expectation is that if the server acts like Vanilla, Velocity will work, and we make special provisions for modded setups where we can. Compatible game versions ------------------------ [Section titled “Compatible game versions”](https://docs.papermc.io/velocity/server-compatibility/#compatible-game-versions) As of this writing, Velocity is compatible with Minecraft 1.7.2 through 26.2. Vanilla setups -------------- [Section titled “Vanilla setups”](https://docs.papermc.io/velocity/server-compatibility/#vanilla-setups) Velocity is best-tested with implementations derived from the Vanilla server by Mojang that do not add content to the game itself. ### Vanilla servers [Section titled “Vanilla servers”](https://docs.papermc.io/velocity/server-compatibility/#vanilla-servers) The Mojang Vanilla software is in a complicated position. It is useful as we often produce protocol updates using the Mojang server for testing, but in production setups, the lack of player info forwarding support can induce subtle client problems. If you plan to run a Vanilla server, **the Velocity team strongly recommends that you use Fabric with the FabricProxy-Lite mod**. Fabric and FabricProxy-Lite do not by themselves change the Vanilla experience, and your server will remain compatible with Vanilla clients. If you are unable (or unwilling) to run Fabric, [VanillaCord](https://github.com/ME1312/VanillaCord) allows you to use legacy BungeeCord forwarding. ### Spigot [Section titled “Spigot”](https://docs.papermc.io/velocity/server-compatibility/#spigot) Spigot is not well-tested with Velocity. However, it is based on Vanilla and as it is the base for Paper, it is relatively well-supported. Spigot does not support Velocity’s modern forwarding, but does support legacy BungeeCord forwarding. ### Paper [Section titled “Paper”](https://docs.papermc.io/velocity/server-compatibility/#paper) The Velocity project recommends using Paper for running a public server. Velocity works with all versions of Paper from 1.7.10 to the latest version. You can use Velocity’s modern forwarding if you run Paper 1.13.2 or higher. If you use Paper 1.12.2 or lower, you must use legacy BungeeCord-style forwarding. ### SpongeVanilla [Section titled “SpongeVanilla”](https://docs.papermc.io/velocity/server-compatibility/#spongevanilla) SpongeVanilla is compatible with legacy BungeeCord-style and modern forwarding. Our Sponge support largely focuses on Forge compatibility, see below for more information. Modded setups ------------- [Section titled “Modded setups”](https://docs.papermc.io/velocity/server-compatibility/#modded-setups) ### Fabric [Section titled “Fabric”](https://docs.papermc.io/velocity/server-compatibility/#fabric) Velocity works with Fabric out of the box, but you should add support for player info forwarding using a mod like [FabricProxy-Lite](https://modrinth.com/mod/fabricproxy-lite) (which supports Velocity modern forwarding). In addition, if you intend to run mods that add new content on top of Vanilla, you should install [CrossStitch](https://modrinth.com/mod/crossstitch) , which improves support for certain Minecraft features that are extended by mods, such as custom argument types. This mod is officially maintained by the Velocity project. ### Minecraft Forge (1.13 and above) [Section titled “Minecraft Forge (1.13 and above)”](https://docs.papermc.io/velocity/server-compatibility/#minecraft-forge-113-and-above) Velocity as of version 3.3.0 supports Forge servers of versions higher than 1.20.2. Support for intermediate versions between 1.13 and 1.20.1 is not planned, however, you can use the [Ambassador](https://modrinth.com/plugin/ambassador) plugin to support these versions. To add modern forwarding support to Forge, you must install the [ProxyCompatibleForge](https://modrinth.com/mod/proxy-compatible-forge) or [SpongeForge](https://spongepowered.org/downloads/spongeforge) mod corresponding to your server version. _Note that SpongeForge is currently in an experimental phase of its Forge support for 1.20.4 versions_. ### Minecraft Forge (1.7.2-1.12.2) [Section titled “Minecraft Forge (1.7.2-1.12.2)”](https://docs.papermc.io/velocity/server-compatibility/#minecraft-forge-172-1122) Minecraft Forge for Minecraft 1.7.2-1.12.2 is fully compatible with Velocity, as we make special provisions to synchronize client state with each server. However, we **strongly** recommend the use of SpongeForge or BungeeForge, as it allows you to use legacy BungeeCord player info forwarding and generally improves proxy support in general. Velocity does not support Forge-Bukkit hybrids - they have caused several issues, and the design of the Bukkit API precludes any notion of sane mod support. Proxy-behind-proxy (BungeeCord, Velocity, …) -------------------------------------------- [Section titled “Proxy-behind-proxy (BungeeCord, Velocity, …)”](https://docs.papermc.io/velocity/server-compatibility/#proxy-behind-proxy-bungeecord-velocity-) These setups are _completely unsupported_. You are best advised to avoid them, as they can cause lots of issues. Most proxy-behind-proxy setups are either illogical in the first place or can be handled more gracefully by better, more scalable and performant solutions. Other implementations --------------------- [Section titled “Other implementations”](https://docs.papermc.io/velocity/server-compatibility/#other-implementations) This is, naturally, not an exhaustive list. Alternative implementations of the Minecraft protocol may or may not work. We encourage you to experiment and to contribute back with your results. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Reference | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/admin/reference/#_top) Reference ========= Reference of Velocity’s configuration options, system properties and other features. [Configuring Velocity](https://docs.papermc.io/velocity/configuration) Velocity is designed to be easy to configure and this guide will walk you through how to do so. [System properties](https://docs.papermc.io/velocity/reference/system-properties) Documentation for the system properties and environment variables Velocity may check. [Built-in commands](https://docs.papermc.io/velocity/built-in-commands) A list of the built-in commands with explanations. [Server compatibility](https://docs.papermc.io/velocity/server-compatibility) A guide to the server compatibility for Velocity. [Comparing with other proxies](https://docs.papermc.io/velocity/comparisons-to-other-proxies) A comparison of Velocity to other proxies. [Libraries used](https://docs.papermc.io/velocity/credits) The credits for all the different libraries used by Velocity. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # API | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/api/#_top) API === Guides for working with Velocity’s API. [Working with events](https://docs.papermc.io/velocity/dev/event-api) How to listen for events in Velocity. [Using the scheduler](https://docs.papermc.io/velocity/dev/scheduler-api) A guide to the Scheduler API within Velocity allowing tasks to be run. [Command API](https://docs.papermc.io/velocity/dev/command-api) How to create commands within Velocity. [Plugin messaging](https://docs.papermc.io/velocity/dev/plugin-messaging) How to handle and send plugin messages on Velocity. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Velocity plugin basics | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/api-basics/#_top) Velocity plugin basics ====================== Now we will lay the groundwork for your first plugin. We will cover how to create your very first Velocity plugin. Create the plugin class ----------------------- [Section titled “Create the plugin class”](https://docs.papermc.io/velocity/dev/api-basics/#create-the-plugin-class) Create a new class (let’s say `com.example.velocityplugin.VelocityTest`) and paste this in: package com.example.velocityplugin; import com.google.inject.Inject;import com.velocitypowered.api.plugin.Plugin;import com.velocitypowered.api.proxy.ProxyServer;import org.slf4j.Logger; @Plugin(id = "myfirstplugin", name = "My First Plugin", version = "0.1.0-SNAPSHOT", url = "https://example.org", description = "I did it!", authors = {"Me"})public class VelocityTest { private final ProxyServer server; private final Logger logger; @Inject public VelocityTest(ProxyServer server, Logger logger) { this.server = server; this.logger = logger; logger.info("Hello there! I made my first plugin with Velocity."); }} What did you just do there? There’s quite a bit to unpack, so let’s focus on the Velocity-specific bits: @Plugin(id = "myfirstplugin", name = "My First Plugin", version = "0.1.0-SNAPSHOT", url = "awesome.org", description = "I did it!", authors = {"Me"})public class VelocityTest { This tells Velocity that this class contains your plugin (`myfirstplugin`) so that it can be loaded once the proxy starts up. Velocity will detect where the plugin will reside when you compile your plugin. Moving on, what’s this? @Injectpublic VelocityTest(ProxyServer server, Logger logger) { this.server = server; this.logger = logger; logger.info("Hello there, it's a test plugin I made!");} This looks like magic! How is Velocity doing this? The answer lies in the [`@Inject`](https://javadoc.io/doc/com.google.inject/guice/latest/com/google/inject/Inject.html) which indicates that Velocity should inject a [`ProxyServer`](https://jd.papermc.io/velocity/com/velocitypowered/api/proxy/ProxyServer.html) and the [`Logger`](https://www.slf4j.org/api/org/slf4j/Logger.html) when constructing your plugin. These two interfaces will help you out as you begin working with Velocity. We won’t talk too much about dependency injection: all you need to know is that Velocity will do this. All you need to do is build your plugin, put it in your `plugins/` directory, and try it! Isn’t that nice? In the next section you’ll learn more about how to use the API. Choosing [`@Plugin`](https://jd.papermc.io/velocity/com/velocitypowered/api/plugin/Plugin.html) information ------------------------------------------------------------------------------------------------------------ [Section titled “Choosing @Plugin information”](https://docs.papermc.io/velocity/dev/api-basics/#choosing-plugin-information) Choose your plugin’s ID wisely. Other plugins will use this ID to depend on yours. If you change it, you could break compatibility. The plugin name is somewhat less important. It will be shown to users as the display name of your plugin, but tweaking it will not be catastrophic. For the version, we recommend sticking to semantic versioning - you can read more about this concept at [semver.org](https://semver.org/) . Basically, use 3 numbers in your version, such as 1.4.25. Increment the major number when you make a backwards-incompatible breaking change, increment the minor number when you add functionality that is backwards compatible, and increment the patch number when you fix a bug or make an otherwise unnoticeable change in the implementation. You can also describe your plugin’s URL, authors, and description in your `@Plugin` annotation. Dependencies on other plugins are also to be specified there, but we’ll get to that later on the [Dependency Management](https://docs.papermc.io/velocity/dev/dependency-management) page. ### A word of caution [Section titled “A word of caution”](https://docs.papermc.io/velocity/dev/api-basics/#a-word-of-caution) Getting your plugin’s directory ------------------------------- [Section titled “Getting your plugin’s directory”](https://docs.papermc.io/velocity/dev/api-basics/#getting-your-plugins-directory) At some point you may need your plugin’s directory. To do this, add `@DataDirectory Path dataDirectory` to your plugin’s constructor parameters: private final Path dataDirectory; @Injectpublic VelocityTest(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { this.server = server; this.logger = logger; this.dataDirectory = dataDirectory;} This will get you a [`Path`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/nio/file/Path.html) of your plugin directory. If you absolutely need a [`File`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/io/File.html) , you may use [`Path#toFile()`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/nio/file/Path.html#toFile()) . However, Velocity usually works with `Path`. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # What does Velocity do for me? | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/why-velocity/#_top) What does Velocity do for me? ============================= We believe that Velocity is one of the best proxies for _Minecraft_ around, and there’s not much that can top it. However, we do diverge from more established, mainstream solutions in some important ways. That can make Velocity a bit hard to sell. We are frequently asked “why?” so often. This page is our answer to that question. Strong experience ----------------- [Section titled “Strong experience”](https://docs.papermc.io/velocity/why-velocity/#strong-experience) The founder and primary developer of Velocity (Tux) has been active in developing proxy software for _Minecraft: Java Edition_ since 2013. They created the RedisBungee plugin, contributed to BungeeCord from 2014 to 2017, and also founded the Waterfall project and led it from 2016 to 2017. In fact, the current maintainer of Waterfall helped encourage them to start a brand-new proxy from the ground up! Leading performance ------------------- [Section titled “Leading performance”](https://docs.papermc.io/velocity/why-velocity/#leading-performance) Velocity powers several highly-populated Minecraft networks, while using fewer resources than the competition. The recipe to the sauce is simple. ### No entity ID rewriting [Section titled “No entity ID rewriting”](https://docs.papermc.io/velocity/why-velocity/#no-entity-id-rewriting) When a Minecraft client connects to another Minecraft server, the server will send back an ID that uniquely identifies a specific player connection. This ID is used in packets that target the player that the server may send. But what happens when they’re actually connected to a proxy that has the ability to change what server the player is connected to? Other proxy solutions try to solve this problem by rewriting entity IDs that reference the current player, changing it from the entity ID assigned by the server the player is currently connected to, to the entity ID that the player got when they connected to the first server they connected to through the proxy. This approach is often complicated, leads to bugs, reduces performance, breaks mods, and ultimately cannot be a complete solution. However, the Minecraft client actually supports changing its entity ID with a special packet sequence. Velocity takes advantage of this and forces the client to change its entity ID. This approach improves performance, improves mod compatibility, and reduces issues caused by incomplete entity ID rewrites. ### Going deep [Section titled “Going deep”](https://docs.papermc.io/velocity/why-velocity/#going-deep) Velocity goes deeper than optimizing the handling of the Minecraft protocol. Smart handling of the protocol produces incredible performance gains but for more performance, we need to go much deeper. One way in which we drastically improve performance and throughput is by improving the speed of compressing packets to be sent to the client. On supported platforms (Linux x86\_64 and aarch64), Velocity is able to replace the zlib library ( which implements the compression algorithm used by the Minecraft protocol) with [libdeflate](https://github.com/ebiggers/libdeflate) which is twice as fast as zlib while delivering a similar compression ratio. Velocity also employs several tricks to get the JIT (just-in-time) compiler on our side. Those tricks require deep understanding of how Java works, but we put in the work to apply those tricks which translate to increased performance. ### Internal stability policies [Section titled “Internal stability policies”](https://docs.papermc.io/velocity/why-velocity/#internal-stability-policies) Finally, Velocity does not attempt to maintain a stable internal API between minor and major releases. This allows Velocity to be more flexible and still deliver performance improvements and new features with each release. For instance, Velocity 1.1.0 delivered massive performance improvements and added many significant new features by breaking parts of the internal API while still keeping full compatibility with older plugins. Compare to BungeeCord which is often very conservative about API breaks and when it does so, provides little notice of the break, and even when doing a break, does not take the opportunity to seriously improve the API being broken (for instance, adding RGB support to `ChatColor`). ### Control is in your hands [Section titled “Control is in your hands”](https://docs.papermc.io/velocity/why-velocity/#control-is-in-your-hands) We take pride in tuning Velocity to be the most performant proxy, but in case the speed provided out-of-the-box is not good enough, you can easily tweak several performance-related settings in `velocity.toml`. Improved security ----------------- [Section titled “Improved security”](https://docs.papermc.io/velocity/why-velocity/#improved-security) Velocity also features more security features, some of which are unique to Velocity. We proactively foreclose as many denial-of-service attacks as soon as possible and feature a unique player info forwarding system for Minecraft 1.13+ that requires the server and proxy to know a pre-arranged key. Standards and mod support ------------------------- [Section titled “Standards and mod support”](https://docs.papermc.io/velocity/why-velocity/#standards-and-mod-support) Unlike certain platforms which only provide lip service to the modding community (and can be at time hostile to them), Velocity embraces the richness of the platform Minecraft provides. As just a small example, we have a Fabric mod that [helps bridge the gap between Velocity itself and mods that extend the Minecraft protocol](https://www.curseforge.com/minecraft/mc-mods/crossstitch) and feature full Forge support for 1.7 through 1.12.2 and 1.20.2 or higher. Velocity also supports emerging standard libraries in the community such as the [Adventure](https://github.com/PaperMC/adventure) library. We collaborate with the Minecraft modding community. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Using the scheduler | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/scheduler-api/#_top) Using the scheduler =================== The Velocity scheduler lets you decide when and how your plugin tasks run, allowing fine control over execution. On Velocity, there is no main thread. All tasks run using the Velocity scheduler are thus run asynchronously. Running a delayed task ---------------------- [Section titled “Running a delayed task”](https://docs.papermc.io/velocity/dev/scheduler-api/#running-a-delayed-task) All scheduling works by using a [`TaskBuilder`](https://jd.papermc.io/velocity/com/velocitypowered/api/scheduler/Scheduler.TaskBuilder.html) returned from the [`Scheduler`](https://jd.papermc.io/velocity/com/velocitypowered/api/scheduler/Scheduler.html) . This fluent builder may be chained to configure the details of the scheduling. server.getScheduler() .buildTask(plugin, () -> { // do stuff here }) .delay(2L, TimeUnit.SECONDS) .schedule(); Here, we are scheduling a task to run 2 seconds later. Velocity requires the instance of your plugin, `plugin` above. If you are scheduling a task from your main plugin class you may simply use `this`. Time arguments are specified as a `long` with a [`TimeUnit`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/TimeUnit.html) . Using time units makes scheduling delayed tasks more readable and allows for greater precision. `2L, TimeUnit.SECONDS` is far easier to understand than the ambiguous `2000L`. You can also use a [`Duration`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/time/Duration.html) to specify the time arguments, e.g.: `Duration.ofSeconds(5L)`. Running a repeating task ------------------------ [Section titled “Running a repeating task”](https://docs.papermc.io/velocity/dev/scheduler-api/#running-a-repeating-task) Creating a repeating task is similar to a delayed task, but you must also specify [`repeat(long, TimeUnit)`](https://jd.papermc.io/velocity/com/velocitypowered/api/scheduler/Scheduler.TaskBuilder.html#repeat(long,java.util.concurrent.TimeUnit)) . This example will repeat every 5 minutes. server.getScheduler() .buildTask(plugin, () -> { // do stuff here }) .repeat(5L, TimeUnit.MINUTES) .schedule(); Running a task now ------------------ [Section titled “Running a task now”](https://docs.papermc.io/velocity/dev/scheduler-api/#running-a-task-now) Tasks use the scheduler’s cached thread pool for all execution, which reuses threads. To take advantage of this thread pool for running async tasks which run now, simply omit calling the _delay_ and _repeat_ methods of the `TaskBuilder`. Cancellation ------------ [Section titled “Cancellation”](https://docs.papermc.io/velocity/dev/scheduler-api/#cancellation) The [`schedule()`](https://jd.papermc.io/velocity/com/velocitypowered/api/scheduler/Scheduler.TaskBuilder.html#schedule()) method returns a [`ScheduledTask`](https://jd.papermc.io/velocity/com/velocitypowered/api/scheduler/ScheduledTask.html) , which may then be used to cancel the task involved via the [`cancel()`](https://jd.papermc.io/velocity/com/velocitypowered/api/scheduler/ScheduledTask.html#cancel()) method. Tasks cannot be uncancelled. Additionally, [`task.status()`](https://jd.papermc.io/velocity/com/velocitypowered/api/scheduler/ScheduledTask.html#status()) returns the current status of the task. ScheduledTask task = server.getScheduler() .buildTask(plugin, () -> { // do stuff here }) .repeat(5L, TimeUnit.MINUTES) .schedule();// ...task.cancel();// ...System.out.println(task.status()); You can also schedule _self-cancelling_ tasks using a `Consumer`. AtomicInteger integer = new AtomicInteger(0); ScheduledTask task = server.getScheduler() .buildTask(plugin, (selfTask) -> { // do stuff here, for example... if (integer.addAndGet(1) > 10) { selfTask.cancel(); } }) .repeat(Duration.ofSeconds(4L)) .schedule(); Obtaining tasks from a plugin ----------------------------- [Section titled “Obtaining tasks from a plugin”](https://docs.papermc.io/velocity/dev/scheduler-api/#obtaining-tasks-from-a-plugin) You can get all tasks scheduled by a plugin with [`tasksByPlugin(Object)`](https://jd.papermc.io/velocity/com/velocitypowered/api/scheduler/Scheduler.html#tasksByPlugin(java.lang.Object)) . Collection tasks = server.getScheduler().tasksByPlugin(plugin);// then you can control them, for example, cancel all task scheduled by a pluginfor (ScheduledTask task : tasks) { task.cancel();} Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Frequently asked questions | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/faq/#_top) Frequently asked questions ========================== Over the years, we’ve been asked many of the same questions by users. This FAQ attempts to answer as many of these questions from the user perspective. What version of Java does Velocity require? ------------------------------------------- [Section titled “What version of Java does Velocity require?”](https://docs.papermc.io/velocity/faq/#what-version-of-java-does-velocity-require) Velocity 3.5.x and above requires at least Java 21. Where can I find Velocity plugins? ---------------------------------- [Section titled “Where can I find Velocity plugins?”](https://docs.papermc.io/velocity/faq/#where-can-i-find-velocity-plugins) A good source for finding plugins compatible with Velocity would be our plugin repository [Hangar](https://hangar.papermc.io/?page=0&platform=VELOCITY) . Does Velocity support plugins developed for BungeeCord or Waterfall? -------------------------------------------------------------------- [Section titled “Does Velocity support plugins developed for BungeeCord or Waterfall?”](https://docs.papermc.io/velocity/faq/#does-velocity-support-plugins-developed-for-bungeecord-or-waterfall) No. Many of the things Velocity can do could not be done if we decided to support BungeeCord plugins. However, certain plugins may have Velocity ports available or alternatives are available. In addition, plugins that support BungeeCord but only require that they are installed on the server (nothing on the proxy) typically use the BungeeCord plugin messaging channel, which is supported natively by the latest versions of Velocity. If no Velocity port or alternative is available, the third-party project [Snap](https://hangar.papermc.io/Phoenix616/Snap) offers an experimental way to run BungeeCord/Waterfall plugins on Velocity. Note that not all plugins may work correctly, so you should always do your own testing. Snap is not maintained by or affiliated with the Velocity project. Help, I can’t connect to my server! ----------------------------------- [Section titled “Help, I can’t connect to my server!”](https://docs.papermc.io/velocity/faq/#help-i-cant-connect-to-my-server) There are a few common causes for why you can’t connect to the server. ### Basic troubleshooting [Section titled “Basic troubleshooting”](https://docs.papermc.io/velocity/faq/#basic-troubleshooting) As a first step, you should verify: * that your servers are started and are responsive to console input * that the proxy is started * that the server and proxy are bound to the appropriate port and IP ### Improper player information forwarding errors [Section titled “Improper player information forwarding errors”](https://docs.papermc.io/velocity/faq/#improper-player-information-forwarding-errors) Can't connect to server lobby: If you wish to use IP forwarding, please enable it in your Bungeecord config as well! Can't connect to server lobby: Your server did not send a forwarding request to the proxy. Is it set up correctly? These errors are result of improper configuration. See [Player Information Forwarding](https://docs.papermc.io/velocity/player-information-forwarding) to learn how to properly set up player information forwarding. Can't connect to server lobby: This server requires you to connect with Velocity. This error is a result of enabling Velocity modern forwarding on your backend server, but not enabling it in Velocity. To fix this error, ensure that you have set up the correct player information forwarding method on the proxy. See [Player Information Forwarding](https://docs.papermc.io/velocity/player-information-forwarding) for more information. ### Invalid payload `REGISTER` [Section titled “Invalid payload REGISTER”](https://docs.papermc.io/velocity/faq/#invalid-payload-register) [server connection] player1 -> hub has connected[connected player] player1 (/localhost:58943): kicked from server hub: Invalid payload REGISTER! This error typically occurs on Spigot-based servers when someone connects with a modded client. You can fix this issue if you use Paper (or a fork of Paper) 1.12.2 or above by adding the startup flag [`-Dpaper.disableChannelLimit=true`](https://docs.papermc.io/paper/reference/system-properties#paperdisablechannellimit) to the server’s startup flags and restarting the server. ### Argument type identifier unknown [Section titled “Argument type identifier unknown”](https://docs.papermc.io/velocity/faq/#argument-type-identifier-unknown) Argument type identifier : unknown. If you receive this message, there are two possibilities. If you run a modded server and are using Fabric 1.16+ and above, update to at least Velocity 1.1.2 and install [CrossStitch](https://www.curseforge.com/minecraft/mc-mods/crossstitch) . (If you are running any other kind of modded server and have it working with Velocity, let us know!) If you receive this message but run a Vanilla server, [please report a bug to the Velocity issue tracker](https://github.com/PaperMC/Velocity/issues/new) . ### Read time out while switching to a Forge server [Section titled “Read time out while switching to a Forge server”](https://docs.papermc.io/velocity/faq/#read-time-out-while-switching-to-a-forge-server) Particularly for some very large mod packs, there is an elevated risk of the connection between the player and the proxy dropping. There is not much we can do on the proxy end to alleviate this. We suggest either reducing the number of mods your server uses, or raise the `read-timeout` setting in `velocity.toml` and add the `-Dfml.readTimeout` startup flag to your Forge server and setting it to the value (in seconds) you chose for the proxy. For instance, if you determine that 120 seconds is the best read timeout to use, use `-Dfml.readTimeout=120` and set `read-timeout = 120000` in `velocity.toml`. ### My forced hosts are not working! [Section titled “My forced hosts are not working!”](https://docs.papermc.io/velocity/faq/#my-forced-hosts-are-not-working) If you are relying on SRV records to direct the player to the proxy, remember that Velocity matches `forced-hosts` using the **hostname the client sends**, which is resolved before the connection — not necessarily the address the player types. To make `forced-hosts` work with a proxy on a non-default port (e.g. `12345`), use this setup: Create DNS records: * **CNAME:** `forced1.example.com → actual.server.address.com` * **SRV:** `_minecraft._tcp.survival → forced1.example.com` (priority: 0, weight: 0, port: 12345) In velocity.toml: [forced-hosts]"forced1.example.com" = ["survival"] # survival.example.com Although the player connects via `survival.example.com`, the SRV record points to `forced1.example.com`, and that is what the client sends to Velocity — allowing it to match correctly in `forced-hosts`. ### Plugins unable to modify messages or commands [Section titled “Plugins unable to modify messages or commands”](https://docs.papermc.io/velocity/faq/#plugins-unable-to-modify-messages-or-commands) A plugin tried to cancel a signed chat message. This is no longer possible in 1.19.1 and newer. Disconnecting player Starting with Minecraft 1.19.1, Mojang implemented a new chat system that encrypts each message with the signed key that each player has. Velocity does not yet have full support for cancelling or modifying this type of messages and commands, so you can install the [SignedVelocity](https://hangar.papermc.io/4drian3d/SignedVelocity) plugin, which will allow the message or command to be transmitted to your server, which, upon receiving it on the server, will apply the result computed in Velocity. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Configuring player information forwarding | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/player-information-forwarding/#_top) Configuring player information forwarding ========================================= Velocity supports forwarding information about your players to your servers, such as IP addresses, UUIDs and skins. Velocity supports three forwarding formats: * **Velocity modern forwarding** is a custom forwarding format (modern forwarding) that is more secure. * **BungeeCord forwarding** (also known as _legacy forwarding_) which has better compatibility but is less secure. * **BungeeGuard**, which is the same as BungeeCord forwarding but includes a secret key. It is better than BungeeCord forwarding alone, but it is less ideal than Velocity modern forwarding. Configuring modern forwarding ----------------------------- [Section titled “Configuring modern forwarding”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-modern-forwarding) `modern` forwarding is a Velocity-native format. It forwards all player information in an efficient binary format and employs a MAC code to make it much more difficult to trick the server into impersonating your Velocity proxy. However, it is only available for Minecraft 1.13 or higher. To use modern forwarding with any supported server implementation, set the `player-info-forwarding-mode` setting in `velocity.toml` to `modern`. Then, you need to ensure your server is properly configured to use Velocity forwarding. ### Configuring modern forwarding for Paper [Section titled “Configuring modern forwarding for Paper”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-modern-forwarding-for-paper) Paper 1.14+ and above, along with Paper 1.13.1/1.13.2 build 377 and above support Velocity modern forwarding natively. First, you need to disable the `online-mode` setting in the [`server.properties`](https://docs.papermc.io/paper/reference/server-properties#online_mode) file. This prevents the server from authenticating players, which the proxy will do instead. You also need to disable BungeeCord forwarding if you had it enabled beforehand. Make sure `settings.bungeecord` is set to `false` in your `spigot.yml`. In `config/paper-global.yml`, set `proxies.velocity.enabled` to true and `proxies.velocity.secret`, to match the secret in your `forwarding.secret` file. You must also set `proxies.velocity.online-mode` to match the `online-mode` setting in your `velocity.toml`. Once you’re done editing `paper-global.yml`, reboot your server. Configuring modern forwarding for Fabric ---------------------------------------- [Section titled “Configuring modern forwarding for Fabric”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-modern-forwarding-for-fabric) A mod called [FabricProxy-Lite](https://modrinth.com/mod/fabricproxy-lite) allows you to use Velocity modern forwarding with a modded server using Fabric. For additional compatibility, you may use the [CrossStitch](https://modrinth.com/mod/crossstitch) mod. Configuring modern forwarding for Forge --------------------------------------- [Section titled “Configuring modern forwarding for Forge”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-modern-forwarding-for-forge) A mod called [ProxyCompatibleForge](https://modrinth.com/mod/proxy-compatible-forge) allows you to use Velocity modern forwarding with a modded server using Forge 1.14 or higher. Configuring legacy BungeeCord-compatible forwarding --------------------------------------------------- [Section titled “Configuring legacy BungeeCord-compatible forwarding”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-legacy-bungeecord-compatible-forwarding) `legacy` forwarding is the player information forwarding protocol that is used by BungeeCord when enabling IP forwarding from BungeeCord. Due to this, it is ubiquitous and well-supported by most server implementations. It has excellent compatibility (supporting versions as old as 1.7.2, released in 2013) and will work with Forge if you also install SpongeForge/BungeeForge on your modded server and configure it correctly. However, it is not secure. If you must use BungeeCord-compatible forwarding, simply set your `player-info-forwarding-mode` setting in `velocity.toml` to `legacy`. You will also need to make sure your server can accept the forwarded player data sent by Velocity. To add some security, particularly for proxies hosted on shared hosting, Velocity optionally supports the [BungeeGuard](https://www.spigotmc.org/resources/bungeeguard.79601/) plugin. To use it, set the `player-info-forwarding-mode` setting in `velocity.toml` to `bungeeguard`, then add the value in the `forwarding.secret` file to the token section in the BungeeGuard configuration. ### Configuring legacy forwarding for Spigot / Paper [Section titled “Configuring legacy forwarding for Spigot / Paper”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-legacy-forwarding-for-spigot--paper) To make Spigot or Paper understand the data forwarded from Velocity, set `settings.bungeecord` to `true` in your `spigot.yml` and then reboot your server. ### Configuring legacy forwarding for Sponge [Section titled “Configuring legacy forwarding for Sponge”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-legacy-forwarding-for-sponge) To configure Sponge to understand the data forwarded from Velocity, you will need to stop the server first, set `modules.bungeecord` to `true` and `bungeecord.ip-forwarding` to `true` in your `config/sponge/global.conf` file, and then restart your Sponge server. ### Configuring legacy forwarding for Forge [Section titled “Configuring legacy forwarding for Forge”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-legacy-forwarding-for-forge) To configure Forge to understand the data forwarded from Velocity, you will need to stop the server first, download your correct [BungeeForge](https://github.com/caunt/BungeeForge/releases) version and place the mod into the mods folder, and then restart your Forge server. ### Configuring legacy forwarding for Fabric [Section titled “Configuring legacy forwarding for Fabric”](https://docs.papermc.io/velocity/player-information-forwarding/#configuring-legacy-forwarding-for-fabric) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Plugin messaging | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/plugin-messaging/#_top) Plugin messaging ================ First introduced in [2012](https://web.archive.org/web/20220711204310/https://dinnerbone.com/blog/2012/01/13/minecraft-plugin-channels-messaging/) , plugin messaging is a way for Velocity plugins to communicate with clients and backend servers. Velocity manages connections in both directions, for both the client and backend server. This means Velocity plugins need to consider 4 main cases: ![Diagram](https://docs.papermc.io/d2/docs/velocity/dev/api/plugin-messaging-0.svg) Additionally, BungeeCord channel compatibility is included, which may remove the need for a companion Velocity plugin in certain cases. Case 1: Receiving a plugin message from a player ------------------------------------------------ [Section titled “Case 1: Receiving a plugin message from a player”](https://docs.papermc.io/velocity/dev/plugin-messaging/#case-1-receiving-a-plugin-message-from-a-player) This is for when you need to handle or inspect the contents of a plugin message sent by a player. It will require registering with the ChannelRegistrar for the event to be fired. An example use case could be logging messages from a mod that reports the enabled features. ![Diagram](https://docs.papermc.io/d2/docs/velocity/dev/api/plugin-messaging-1.svg) public static final MinecraftChannelIdentifier IDENTIFIER = MinecraftChannelIdentifier.from("custom:main"); @Subscribepublic void onProxyInitialization(ProxyInitializeEvent event) { proxyServer.getChannelRegistrar().register(IDENTIFIER);} @Subscribepublic void onPluginMessageFromPlayer(PluginMessageEvent event) { // Check if the identifier matches first, no matter the source. if (!IDENTIFIER.equals(event.getIdentifier())) { return; } // mark PluginMessage as handled, indicating that the contents // should not be forwarding to their original destination. event.setResult(PluginMessageEvent.ForwardResult.handled()); // Alternatively: // mark PluginMessage as forwarded, indicating that the contents // should be passed through, as if Velocity is not present. //event.setResult(PluginMessageEvent.ForwardResult.forward()); // only attempt parsing the data if the source is a player if (!(event.getSource() instanceof Player player)) { return; } ByteArrayDataInput in = ByteStreams.newDataInput(event.getData()); // handle packet data} Case 2: Sending a plugin message to a backend server ---------------------------------------------------- [Section titled “Case 2: Sending a plugin message to a backend server”](https://docs.papermc.io/velocity/dev/plugin-messaging/#case-2-sending-a-plugin-message-to-a-backend-server) This is for when you need to send a plugin message to a backend server. There are two methods to send a plugin message to the backend, depending on what you need to achieve. ![Diagram](https://docs.papermc.io/d2/docs/velocity/dev/api/plugin-messaging-2.svg) ### Using any connected player [Section titled “Using any connected player”](https://docs.papermc.io/velocity/dev/plugin-messaging/#using-any-connected-player) This is useful if you just want to communicate something relevant to the entire server, or otherwise can be derived from its content. An example use case could be telling the server to shut down. public boolean sendPluginMessageToBackend(RegisteredServer server, ChannelIdentifier identifier, byte[] data) { // On success, returns true return server.sendPluginMessage(identifier, data);} ### Using a specific player’s connection [Section titled “Using a specific player’s connection”](https://docs.papermc.io/velocity/dev/plugin-messaging/#using-a-specific-players-connection) This is useful if you want to communicate something about a specific player to their current backend server. You may want additional checks to ensure it will be handled correctly on the backend the player is on. An example use case could be telling the backend server to give the player a specific item. public boolean sendPluginMessageToBackendUsingPlayer(Player player, ChannelIdentifier identifier, byte[] data) { Optional connection = player.getCurrentServer(); if (connection.isPresent()) { // On success, returns true return connection.get().sendPluginMessage(identifier, data); } return false;} Case 3: Receiving a plugin message from a backend server -------------------------------------------------------- [Section titled “Case 3: Receiving a plugin message from a backend server”](https://docs.papermc.io/velocity/dev/plugin-messaging/#case-3-receiving-a-plugin-message-from-a-backend-server) This is for when you need to receive plugin messages from your backend server. It will require registering with the [`ChannelRegistrar`](https://jd.papermc.io/velocity/com/velocitypowered/api/proxy/messages/ChannelRegistrar.html) for the event to be fired. An example use case could be handing a request to transfer the player to another server. ![Diagram](https://docs.papermc.io/d2/docs/velocity/dev/api/plugin-messaging-3.svg) public static final MinecraftChannelIdentifier IDENTIFIER = MinecraftChannelIdentifier.from("custom:main"); @Subscribepublic void onProxyInitialization(ProxyInitializeEvent event) { proxyServer.getChannelRegistrar().register(IDENTIFIER);} @Subscribepublic void onPluginMessageFromBackend(PluginMessageEvent event) { // Check if the identifier matches first, no matter the source. // this allows setting all messages to IDENTIFIER as handled, // preventing any client-originating messages from being forwarded. if (!IDENTIFIER.equals(event.getIdentifier())) { return; } // mark PluginMessage as handled, indicating that the contents // should not be forwarding to their original destination. event.setResult(PluginMessageEvent.ForwardResult.handled()); // Alternatively: // mark PluginMessage as forwarded, indicating that the contents // should be passed through, as if Velocity is not present. // // this should be used with extreme caution, // as any client can freely send whatever it wants, pretending to be the proxy //event.setResult(PluginMessageEvent.ForwardResult.forward()); // only attempt parsing the data if the source is a backend server if (!(event.getSource() instanceof ServerConnection backend)) { return; } ByteArrayDataInput in = ByteStreams.newDataInput(event.getData()); // handle packet data} Case 4: Sending a plugin message to a player -------------------------------------------- [Section titled “Case 4: Sending a plugin message to a player”](https://docs.papermc.io/velocity/dev/plugin-messaging/#case-4-sending-a-plugin-message-to-a-player) This is for when you need to send a plugin message to a player. ![Diagram](https://docs.papermc.io/d2/docs/velocity/dev/api/plugin-messaging-4.svg) public boolean sendPluginMessageToPlayer(Player player, ChannelIdentifier identifier, byte[] data) { // On success, returns true return player.sendPluginMessage(identifier, data);} BungeeCord channel compatibility -------------------------------- [Section titled “BungeeCord channel compatibility”](https://docs.papermc.io/velocity/dev/plugin-messaging/#bungeecord-channel-compatibility) This allows your backend servers to communicate with Velocity in a way compatible with BungeeCord. By default, your Velocity server will respond to the `bungeecord:main` channel, if `bungee-plugin-message-channel` is enabled in [the configuration](https://docs.papermc.io/velocity/configuration#advanced-section) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Working with events | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/event-api/#_top) Working with events =================== Listening to events with Velocity’s `@Subscribe` annotation is straightforward. You’ve already seen one such listener, using [`ProxyInitializeEvent`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/proxy/ProxyInitializeEvent.html) in your main class. Additional events can be found on the [Javadoc](https://jd.papermc.io/velocity) . Creating a listener method -------------------------- [Section titled “Creating a listener method”](https://docs.papermc.io/velocity/dev/event-api/#creating-a-listener-method) To listen to an event, mark the method with [`@Subscribe`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/Subscribe.html) , like shown. This works similarly to annotation-driven event listening in other APIs you may be familiar with; it’s the equivalent of Bukkit’s/Bungee’s `@EventHandler` and Sponge’s `@Listener`. @Subscribepublic void onPlayerChat(PlayerChatEvent event) { // do stuff} Orders ------ [Section titled “Orders”](https://docs.papermc.io/velocity/dev/event-api/#orders) Every listener has a [`priority`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/Subscribe.html#priority()) . When an event is fired, the order in which listeners are invoked is defined by their `priority`. The higher the priority, the earlier the event handler will be called. State the desired order in the `@Subscribe` annotation: @Subscribe(priority = 10)public void onPlayerChatFirst(PlayerChatEvent event) { // this method fires first} @Subscribe(priority = 5)public void onPlayerChat(PlayerChatEvent event) { // this method fires after the one above} `0` is the default value if you do not specify an order. Registering listeners --------------------- [Section titled “Registering listeners”](https://docs.papermc.io/velocity/dev/event-api/#registering-listeners) Velocity automatically registers your main plugin class as an event listener. This is handy for initialization and for simple plugins, but for more complex plugins, you will want to separate your event handlers from the main plugin class. To do so, you will need to register with the [`EventManager`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/EventManager.html) any other listeners you have: The event system supports registering an object as a listener (allowing you to use `@Subscribe` to mark event handlers) or registering functional listeners. ### Registering an object as a listener [Section titled “Registering an object as a listener”](https://docs.papermc.io/velocity/dev/event-api/#registering-an-object-as-a-listener) server.getEventManager().register(plugin, listener); Both parameters are [`Object`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Object.html) . The first argument is your plugin’s object, and the second argument should be the listener to register. For example: @Plugin(id = "myfirstplugin", name = "My Plugin", version = "0.1.0", dependencies = {@Dependency(id = "wonderplugin")})public class VelocityTest { private final ProxyServer server; private final Logger logger; @Inject public VelocityTest(ProxyServer server, Logger logger) { this.server = server; this.logger = logger; } @Subscribe public void onInitialize(ProxyInitializeEvent event) { server.getEventManager().register(this, new MyListener()); }} public class MyListener { @Subscribe public void onPlayerChat(PlayerChatEvent event) { // do something here } } ### Registering a functional-style listener [Section titled “Registering a functional-style listener”](https://docs.papermc.io/velocity/dev/event-api/#registering-a-functional-style-listener) As an alternative to `@Subscribe`, you can also use the functional `EventHandler` interface and register yours with [`register(Object plugin, Class eventClass, EventHandler handler)`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/EventManager.html#register(java.lang.Object,java.lang.Class,com.velocitypowered.api.event.EventHandler)) : server.getEventManager().register(this, PlayerChatEvent.class, event -> { // do something here }); Handling events asynchronously ------------------------------ [Section titled “Handling events asynchronously”](https://docs.papermc.io/velocity/dev/event-api/#handling-events-asynchronously) In Velocity 3.0.0, events can now be handled asynchronously. The event system allows a plugin to pause sending an event to every listener, perform some unit of computation or I/O asynchronously, and then resume processing the event. All Velocity events have the ability to be processed asynchronously, however only some will explicitly wait for events to finish being fired before continuing. For an annotation-based listener, all that is needed to process an event asynchronously is to either return an [`EventTask`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/EventTask.html) or add a second return an [`Continuation`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/Continuation.html) parameter: @Subscribe(priority = 100) public void onLogin(LoginEvent event, Continuation continuation) { doSomeAsyncProcessing().whenComplete((_, throwable) -> { if (throwable != null) { continuation.resumeWithException(throwable); } else { continuation.resume(); } }); } private CompletableFuture doSomeAsyncProcessing() { //... } @Subscribe(priority = 100) public EventTask onPlayerChat(PlayerChatEvent event) { if (mustFurtherProcess(event)) { return EventTask.async(() => ...); } return null; } A functional listener simply needs to implement [`AwaitingEventExecutor`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/AwaitingEventExecutor.html) and return an [`EventTask`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/EventTask.html) : server.getEventManager().register(this, PlayerChatEvent.class, (AwaitingEventExecutor) event -> { if (mustFurtherProcess(event)) { return EventTask.async(() => ...); } return null; }); There are two types of event tasks: * **Async tasks** simply run a unit of execution asynchronously. To get a basic event task, use [`EventTask.async(Runnable)`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/EventTask.html#async(java.lang.Runnable)) . Basic event tasks are the closest equivalent for Velocity 1.x.x event listeners and asynchronous events in the Bukkit API. * **Continuation tasks** provide the listener with a callback (known as a `Continuation`) to resume event processing when the (possibly asynchronous) work is completed. To get a continuation-based event task, use [`EventTask.withContinuation(Consumer)`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/EventTask.html#withContinuation(java.util.function.Consumer)) . Continuation-based tasks are the closest equivalent for listeners that use BungeeCord `AsyncEvent` intents, but have a slightly different programming model in that each listener still runs sequentially, just that an individual listener can defer passing control onto the next listener until it is done. Creating events --------------- [Section titled “Creating events”](https://docs.papermc.io/velocity/dev/event-api/#creating-events) Creating events on Velocity is somewhat different than on other platforms. However, it is very similar for the most part. ### Creating the event class [Section titled “Creating the event class”](https://docs.papermc.io/velocity/dev/event-api/#creating-the-event-class) First we need to create a class for our event. In this tutorial we’ll assume you’re making a private messaging plugin, and thus use a `PrivateMessageEvent`. Most of this part is boilerplate. public class PrivateMessageEvent { private final Player sender; private final Player recipient; private final String message; public PrivateMessageEvent(Player sender, Player recipient, String message) { this.sender = sender; this.recipient = recipient; this.message = message; } public Player sender() { return sender; } public Player recipient() { return recipient; } public String message() { return message; } // toString, equals, and hashCode may be added as needed } You’ll notice that your events don’t need to extend or implement anything. They just work. ### Firing the Event [Section titled “Firing the Event”](https://docs.papermc.io/velocity/dev/event-api/#firing-the-event) To fire the event, you’ll need to get the server’s event manager and use the [`fire`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/EventManager.html#fire(E)) method. Note that this returns a [`CompletableFuture`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/CompletableFuture.html) , so if you want to continue logic after the event is handled by all listeners, use a callback: server.getEventManager().fire(new PrivateMessageEvent(sender, recipient, message)).thenAccept((event) -> { // event has finished firing // do some logic dependent on the result}); ### Using `ResultedEvent` [Section titled “Using ResultedEvent”](https://docs.papermc.io/velocity/dev/event-api/#using-resultedevent) Velocity uses the generalized [`ResultedEvent`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/ResultedEvent.html) for events which have some sort of ‘result’. The result type of the event is defined by its generic type; for example `PrivateMessageEvent implements ResultedEvent`. Some common result types are [`GenericResult`](https://jd.papermc.io/velocity/com/velocitypowered/api/event/ResultedEvent.GenericResult.html) , for simple allowed/denied results, and component results, used for events where the result may be denied with an accompanying reason (such as in a login event). Using a general result is far more encompassing than `isCancelled/setCancelled` methods you may be used to on other platforms, whose meaning is vague and limited to a simple boolean. In this example, we’ll use `GenericResult`, so listeners will be able to mark our `PrivateMessageEvent` as either allowed or denied. public class PrivateMessageEvent implements ResultedEvent { private final Player sender; private final Player recipient; private final String message; private GenericResult result = GenericResult.allowed(); // Allowed by default public PrivateMessageEvent(Player sender, Player recipient, String message) { this.sender = sender; this.recipient = recipient; this.message = message; } public Player sender() { return sender; } public Player recipient() { return recipient; } public String message() { return message; } @Override public GenericResult result() { return result; } @Override public void setResult(GenericResult result) { this.result = Objects.requireNonNull(result); } } Per convention, the result of a `ResultedEvent` should never be null. Here, we assure that using [`Objects#requireNonNull(Object)`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Objects.html#requireNonNull(T)) . Listeners may ‘deny’ the event by using `event.setResult(GenericResult.denied())`, and you may check the result with `event.getResult()`. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Command API | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/command-api/#_top) Command API =========== The command API lets you create commands that can be executed by a player connected to the proxy or the console. Creating a command ------------------ [Section titled “Creating a command”](https://docs.papermc.io/velocity/dev/command-api/#creating-a-command) Each command class needs to implement a [`Command`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/Command.html) sub-interface. The choice depends on the type of arguments and the granularity of suggestions provided to the client. These include: ### [`BrigadierCommand`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/BrigadierCommand.html) [Section titled “BrigadierCommand”](https://docs.papermc.io/velocity/dev/command-api/#brigadiercommand) Internally, Velocity uses the [Brigadier](https://github.com/Mojang/brigadier) library to register and dispatch command actions. You can register your own `CommandNode`s by wrapping them in a `BrigadierCommand`. Let’s see an example of a command that will tell whoever executes the command “Hello World” in light blue text. package com.example.velocityplugin; import com.mojang.brigadier.arguments.StringArgumentType;import com.mojang.brigadier.Command;import com.mojang.brigadier.tree.LiteralCommandNode;import com.velocitypowered.api.command.BrigadierCommand;import com.velocitypowered.api.command.CommandSource;import com.velocitypowered.api.command.VelocityBrigadierMessage;import com.velocitypowered.api.proxy.ProxyServer;import net.kyori.adventure.text.Component;import net.kyori.adventure.text.format.NamedTextColor; public final class TestBrigadierCommand { public static BrigadierCommand createBrigadierCommand(final ProxyServer proxy) { LiteralCommandNode helloNode = BrigadierCommand.literalArgumentBuilder("test") // Here you can filter the subjects that can execute the command. // This is the ideal place to do "hasPermission" checks .requires(source -> source.hasPermission("test.permission")) // Here you can add the logic that will be used in // the execution of the "/test" command without any argument .executes(context -> { // Here you get the subject that executed the command CommandSource source = context.getSource(); Component message = Component.text("Hello World", NamedTextColor.AQUA); source.sendMessage(message); // Returning Command.SINGLE_SUCCESS means that the execution was successful // Returning BrigadierCommand.FORWARD will send the command to the server return Command.SINGLE_SUCCESS; }) // Using the "then" method, you can add sub-arguments to the command. // For example, this subcommand will be executed when using the command "/test " // A RequiredArgumentBuilder is a type of argument in which you can enter some undefined data // of some kind. For example, this example uses a StringArgumentType.word() that requires // a single word to be entered, but you can also use different ArgumentTypes provided by Brigadier // that return data of type Boolean, Integer, Float, other String types, etc .then(BrigadierCommand.requiredArgumentBuilder("argument", StringArgumentType.word()) // Here you can define the hints to be provided in case the ArgumentType does not provide them. // In this example, the names of all connected players are provided .suggests((ctx, builder) -> { // Here we provide the names of the players along with a tooltip, // which can be used as an explanation of a specific argument or as a simple decoration proxy.getAllPlayers().forEach(player -> builder.suggest( player.getUsername(), // A VelocityBrigadierMessage takes a component. // In this case, the player's name is provided with a rainbow // gradient created using MiniMessage. VelocityBrigadierMessage.tooltip( MiniMessage.miniMessage().deserialize("" + player.getUsername()) ) )); // If you do not need to add a tooltip to the hint // or your command is intended only for versions lower than Minecraft 1.13, // you can omit adding the tooltip, since for older clients, // the tooltip will not be displayed. builder.suggest("all"); return builder.buildFuture(); }) // Here the logic of the command "/test " is executed .executes(context -> { // Here you get the argument that the CommandSource has entered. // You must enter exactly the name as you have named the argument // and you must provide the class of the argument you expect, in this case... a String String argumentProvided = context.getArgument("argument", String.class); // This method will check if the given string corresponds to a // player's name and if it does, it will send a message to that player proxy.getPlayer(argumentProvided).ifPresent(player -> player.sendMessage(Component.text("Hello!")) ); // Returning Command.SINGLE_SUCCESS means that the execution was successful // Returning BrigadierCommand.FORWARD will send the command to the server return Command.SINGLE_SUCCESS; }) ) .build(); // BrigadierCommand implements Command return new BrigadierCommand(helloNode); }} Brigadier commands have full backward compatibility with 1.12.2 and lower versions. Custom plugin command argument types are not supported in Velocity, as they would require the client to also support them. We recommend sticking to the predefined Brigadier types provided. ### [`SimpleCommand`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/SimpleCommand.html) [Section titled “SimpleCommand”](https://docs.papermc.io/velocity/dev/command-api/#simplecommand) Modeled after the convention popularized by Bukkit and BungeeCord, a `SimpleCommand` has three methods: one for when the command is executed, one to provide suggestions for tab completion, and one to check a [`CommandSource`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/CommandSource.html) has permission to use the command. All methods receive a [`SimpleCommand.Invocation`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/SimpleCommand.Invocation.html) object, which contains the `CommandSource` that executed the command and the arguments as an array of strings. The previous example can also be implemented using this interface: package com.example.velocityplugin; import com.velocitypowered.api.command.CommandSource;import com.velocitypowered.api.command.SimpleCommand;import java.util.concurrent.CompletableFuture;import java.util.List;import net.kyori.adventure.text.Component;import net.kyori.adventure.text.format.NamedTextColor; public final class TestCommand implements SimpleCommand { @Override public void execute(final Invocation invocation) { CommandSource source = invocation.source(); // Get the arguments after the command alias String[] args = invocation.arguments(); source.sendMessage(Component.text("Hello World!", NamedTextColor.AQUA)); } // This method allows you to control who can execute the command. // If the executor does not have the required permission, // the execution of the command and the control of its autocompletion // will be sent directly to the server on which the sender is located @Override public boolean hasPermission(final Invocation invocation) { return invocation.source().hasPermission("command.test"); } // With this method you can control the suggestions to send // to the CommandSource according to the arguments // it has already written or other requirements you need @Override public List suggest(final Invocation invocation) { return List.of(); } // Here you can offer argument suggestions in the same way as the previous method, // but asynchronously. It is recommended to use this method instead of the previous one // especially in cases where you make a more extensive logic to provide the suggestions @Override public CompletableFuture> suggestAsync(final Invocation invocation) { return CompletableFuture.completedFuture(List.of()); }} It’s important to note [`invocation.arguments()`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/CommandInvocation.html#arguments()) doesn’t include the command alias (e.g. `teleport` for `/teleport foo bar`). In the event that no arguments are specified, an empty array will be passed, rather than a null array. If a player or the console executes the following command: `/stats Player2 kills`, the first argument will be `Player2`, which we can access using `invocation.arguments()[0]` and the second argument will be `kills`. ### [`RawCommand`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/RawCommand.html) [Section titled “RawCommand”](https://docs.papermc.io/velocity/dev/command-api/#rawcommand) There’s certain cases where you don’t need to process the arguments. These may include: * A `/say` style command, where the arguments contain the message as a string; or * You’re using an external command framework to process your commands. A raw command indicates the proxy to pass the command alias and its arguments directly without further processing. Let’s see an example of a command that echoes the received input: package com.example.velocityplugin; import com.velocitypowered.api.command.RawCommand;import net.kyori.adventure.text.Component; public final class EchoCommand implements RawCommand { @Override public void execute(final Invocation invocation) { invocation.source().sendMessage(Component.text(invocation.arguments())); } @Override public boolean hasPermission(final Invocation invocation) { return invocation.source().hasPermission("command.echo"); }} Registering a command --------------------- [Section titled “Registering a command”](https://docs.papermc.io/velocity/dev/command-api/#registering-a-command) Now that we have created a command, we need to register it in order for it to work. To register commands, you use the [`CommandManager`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/CommandManager.html) . We get the command manager by executing [`proxyServer.getCommandManager()`](https://jd.papermc.io/velocity/com/velocitypowered/api/proxy/ProxyServer.html#getCommandManager()) with the proxy instance, or by injecting it using the [`@Inject`](https://javadoc.io/doc/com.google.inject/guice/latest/com/google/inject/Inject.html) annotation in the main class. The register method requires two parameters, the command metadata and the command object. The [`CommandMeta`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/CommandMeta.html) contains the case-insensitive aliases and more advanced features. `CommandManager` provides a meta builder via the [`#metaBuilder(String alias)`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/CommandManager.html#metaBuilder(java.lang.String)) method. package com.example.velocityplugin; import com.google.inject.Inject;import com.velocitypowered.api.command.BrigadierCommand;import com.velocitypowered.api.event.Subscribe;import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;import com.velocitypowered.api.plugin.Plugin;import com.velocitypowered.api.proxy.ProxyServer; @Plugin(id = "helloworld")public final class HelloWorldPlugin { private final ProxyServer proxy; @Inject public HelloWorldPlugin(ProxyServer proxy) { this.proxy = proxy; } @Subscribe public void onProxyInitialize(ProxyInitializeEvent event) { CommandManager commandManager = proxy.getCommandManager(); // Here you can add meta for the command, as aliases and the plugin to which it belongs (RECOMMENDED) CommandMeta commandMeta = commandManager.metaBuilder("test") // This will create a new alias for the command "/test" // with the same arguments and functionality .aliases("otherAlias", "anotherAlias") .plugin(this) .build(); // You can replace this with "new EchoCommand()" or "new TestCommand()" // SimpleCommand simpleCommand = new TestCommand(); // RawCommand rawCommand = new EchoCommand(); // The registration is done in the same way, since all 3 interfaces implement "Command" BrigadierCommand commandToRegister = TestBrigadierCommand.createBrigadierCommand(proxy); // Finally, you can register the command commandManager.register(commandMeta, commandToRegister); }} If you’re registering a `BrigadierCommand`, you may prefer to use the [`#register(BrigadierCommand)`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/CommandManager.html#register(com.velocitypowered.api.command.BrigadierCommand)) method or [`#metaBuilder(BrigadierCommand)`](https://jd.papermc.io/velocity/com/velocitypowered/api/command/CommandManager.html#metaBuilder(com.velocitypowered.api.command.BrigadierCommand)) to specify additional aliases. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # System properties | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/reference/system-properties/#_top) System properties ================= These system properties and environment variables can be set when you start your server allowing for the configuration of various settings. How they work ------------- [Section titled “How they work”](https://docs.papermc.io/velocity/reference/system-properties/#how-they-work) System properties are set when you start your server. For example, if you are using a `.bat` or a `.sh` file to start your server, you can add the system properties to the file. For example: java -Dvelocity.packet-decode-logging=true -jar velocity.jar Where a `-D` is used to set a system property, and the system property is `velocity.packet-decode-logging` with a value of `true`. Otherwise, just add them to the start command. List of system properties ------------------------- [Section titled “List of system properties”](https://docs.papermc.io/velocity/reference/system-properties/#list-of-system-properties) #### auth.forceSecureProfiles [Section titled “auth.forceSecureProfiles”](https://docs.papermc.io/velocity/reference/system-properties/#authforcesecureprofiles) * **default**: `true` * **description**: Overrides `force-key-authentication` from the config. If not set, it will be automatically set to the current config value. #### mojang.sessionserver [Section titled “mojang.sessionserver”](https://docs.papermc.io/velocity/reference/system-properties/#mojangsessionserver) * **default**: `https://sessionserver.mojang.com/session/minecraft/hasJoined` * **description**: Full URL of the `hasJoined` endpoint on the session server used for authentication. #### velocity.natives-tmpdir [Section titled “velocity.natives-tmpdir”](https://docs.papermc.io/velocity/reference/system-properties/#velocitynatives-tmpdir) * **default**: `unset` * **description**: Temporary directory for Velocity native files. (If set, it will also define `io.netty.native.workdir`) #### velocity.max-known-packs [Section titled “velocity.max-known-packs”](https://docs.papermc.io/velocity/reference/system-properties/#velocitymax-known-packs) * **default**: `64` * **description**: Limits known packs to the Vanilla default to prevent crashing Velocity. #### velocity.max-clientside-plugin-channels [Section titled “velocity.max-clientside-plugin-channels”](https://docs.papermc.io/velocity/reference/system-properties/#velocitymax-clientside-plugin-channels) * **default**: `1024` * **description**: Limits the plugin messaging channels registered by the client, as both Velocity and the backend servers need to keep track of them. #### velocity.max-packets-per-flush [Section titled “velocity.max-packets-per-flush”](https://docs.papermc.io/velocity/reference/system-properties/#velocitymax-packets-per-flush) * **default**: `8192` * **description**: The max amount of packets before the queue is flushed automatically. #### velocity.log-server-backpressure [Section titled “velocity.log-server-backpressure”](https://docs.papermc.io/velocity/reference/system-properties/#velocitylog-server-backpressure) * **default**: `false` * **description**: Whether Velocity should log if the server connection is writable and thus if the player connection will be auto-read. #### velocity.packet-decode-logging [Section titled “velocity.packet-decode-logging”](https://docs.papermc.io/velocity/reference/system-properties/#velocitypacket-decode-logging) * **default**: `false` * **description**: Whether packet decoding errors should be logged extensively. #### velocity.skip-uncompressed-packet-size-validation [Section titled “velocity.skip-uncompressed-packet-size-validation”](https://docs.papermc.io/velocity/reference/system-properties/#velocityskip-uncompressed-packet-size-validation) * **default**: `false` * **description**: Whether to skip the validation of uncompressed packet sizes, this is useful to allow modded setups to send uncompressed packets over the threshold. #### velocity.increased-compression-cap [Section titled “velocity.increased-compression-cap”](https://docs.papermc.io/velocity/reference/system-properties/#velocityincreased-compression-cap) * **default**: `false` * **description**: Whether the maximum uncompressed packet size should be set to its maximum supported limit (128 MiB) instead of the Vanilla limit (8 MiB). #### velocity.disable-native-transport [Section titled “velocity.disable-native-transport”](https://docs.papermc.io/velocity/reference/system-properties/#velocitydisable-native-transport) * **default**: `false` * **description**: Whether to disable Netty’s native transport methods like the io\_uring support and Epoll. If set to true, Velocity will use Java’s NIO transport instead. #### velocity.enable-iouring-transport [Section titled “velocity.enable-iouring-transport”](https://docs.papermc.io/velocity/reference/system-properties/#velocityenable-iouring-transport) * **default**: `false` * **description**: Enables Netty’s io\_uring transport when set to true. By default, Velocity only uses the Epoll (on Linux) and kqueue (on macOS) native transports. This property does not override the `velocity.disable-native-transport` property. #### velocity.natives-disabled [Section titled “velocity.natives-disabled”](https://docs.papermc.io/velocity/reference/system-properties/#velocitynatives-disabled) * **default**: `false` * **description**: Whether native functionality for specific operating systems should be disabled. #### velocity.legacyChatMaxServerboundLength [Section titled “velocity.legacyChatMaxServerboundLength”](https://docs.papermc.io/velocity/reference/system-properties/#velocitylegacychatmaxserverboundlength) * **default**: `100` * **description**: Overrides the max chat input length for versions below 1.11. This is useful for mods that backport the modern chat limit of `256`. #### velocity.strictErrorHandling [Section titled “velocity.strictErrorHandling”](https://docs.papermc.io/velocity/reference/system-properties/#velocitystricterrorhandling) * **default**: `true` * **description**: Whether the client should disconnect on packet errors. Temporarily added in MC 1.20.5 and removed in 1.21.2 to help modded servers transition to this change. #### velocity.maximum-play-queue-size [Section titled “velocity.maximum-play-queue-size”](https://docs.papermc.io/velocity/reference/system-properties/#velocitymaximum-play-queue-size) * **default**: `134217728` (128 MiB) * **description**: The maximum size of the queue (in bytes) that holds pending PLAY state packets sent to the client while it is in the CONFIG state. #### velocity.max-plugin-message-payload-size [Section titled “velocity.max-plugin-message-payload-size”](https://docs.papermc.io/velocity/reference/system-properties/#velocitymax-plugin-message-payload-size) * **default**: `32767` * **description**: The maximum allowed size of plugin message packets in bytes. List of environment variables ----------------------------- [Section titled “List of environment variables”](https://docs.papermc.io/velocity/reference/system-properties/#list-of-environment-variables) #### VELOCITY\_FORWARDING\_SECRET [Section titled “VELOCITY\_FORWARDING\_SECRET”](https://docs.papermc.io/velocity/reference/system-properties/#velocity_forwarding_secret) * **default**: `unset` * **description**: Overrides the forwarding secret inside the [`forwarding-secret-file`](https://docs.papermc.io/velocity/configuration#root-section) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Tuning Velocity | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/tuning/#_top) Tuning Velocity =============== Velocity comes with good performance out of the box. We go in deep, starting from smart algorithmic choices, making strategic usage of native libraries, all the way to the JVM level, optimizing the proxy so that the JVM will make better decisions when optimizing the code. Host the proxy on Linux ----------------------- [Section titled “Host the proxy on Linux”](https://docs.papermc.io/velocity/tuning/#host-the-proxy-on-linux) Velocity comes with high-performance, specially tuned native libraries for compression and encryption, along with including native transports from Netty. However, due to support constraints, the compiled natives are only verified to work on Linux x86\_64 and aarch64. While Velocity does not require the natives to work, you will suffer from degraded performance. For this reason, we strongly recommend that all production deployments of Velocity run on x86\_64 Linux. Allocate server resources appropriately --------------------------------------- [Section titled “Allocate server resources appropriately”](https://docs.papermc.io/velocity/tuning/#allocate-server-resources-appropriately) You should always make sure to allocate the correct amount of heap, network bandwidth, and get the right CPU for the amount of players you want to have on your proxy at a given time. For instance, it is unlikely you’ll be able to get 1,000 players on a Raspberry Pi Zero, but you’ll have a much better chance if you have a recent high-end server CPU from Intel or AMD. There is no “one-size-fits-all” hardware recommendation, only general guidelines for the amount of players you can expect: * Prefer lots of cores but lower clock speeds. Unlike the Minecraft server, Velocity can actually benefit from the extra cores and single-threaded performance is not as important. * You should always have enough memory to run Velocity, including room for JVM overhead and for your operating system. For a rough minimum recommended memory amount, double the size of the proxy heap and then add 2GB. For instance, for a proxy with a 2GB heap, plan on getting at least 6GB of memory. * Disk speed is unimportant. A solid-state drive is nice to have but not strictly required. Likewise, disk capacity is unimportant as well. ### Special notes regarding speculative execution security vulnerabilities [Section titled “Special notes regarding speculative execution security vulnerabilities”](https://docs.papermc.io/velocity/tuning/#special-notes-regarding-speculative-execution-security-vulnerabilities) Starting in 2018, a number of security vulnerabilities with regard to [speculative execution](https://en.wikipedia.org/wiki/Speculative_execution) used by modern CPUs have been discovered. The mitigations to these vulnerabilities can have painful performance implications, especially on processors vulnerable to Meltdown and further compounded if running in a virtual machine. Velocity, as a network application, is particularly sensitive to the performance hits that the mitigations introduce. To minimize these hits, we recommend hosting your proxy on a machine with a CPU that has mitigations against Spectre and Meltdown. Processors released in 2019 and onwards typically contain mitigations to protect against Spectre and Meltdown. If you are using a CPU vulnerable to Spectre and/or Meltdown and are willing to risk security for performance, it is also possible to disable Spectre/Meltdown mitigations depending on the operating system you use. Note however that you disable these security mitigations _at your own risk_. The Velocity project does not recommend that you disable these mitigations. Allocate enough heap -------------------- [Section titled “Allocate enough heap”](https://docs.papermc.io/velocity/tuning/#allocate-enough-heap) Alongside having enough CPU, memory, and network bandwidth, you must also allocate enough Java heap to the proxy. Not doing this can induce lag and in severe cases may result in the proxy being terminated by the Java Virtual Machine because it ran out of memory. The general rule of thumb is that you allocate 512MB per 500 players, plus some extra to allow for some room for error (typically 1GB extra). For instance, if you want to handle 1,000 on a single proxy, plan to allocate 2GB of heap. ### Special notes for containers [Section titled “Special notes for containers”](https://docs.papermc.io/velocity/tuning/#special-notes-for-containers) **If you use a containerized setup (such as using Kubernetes, Pterodactyl, or Docker directly), you should not allocate the entirety of your memory allocation to the heap!** Doing so _will_ likely cause the proxy to be killed by the kernel’s out-of-memory killer, which will result in your proxy going down, likely at the worst possible time. A safe (albeit conservative) setting for the heap would be to allocate half of the memory you allocate to the proxy container in total. For instance, if you know the proxy will need to hold 1,000 players, then allocate 4GB to the container and give the proxy 2GB of heap. Tune your startup flags ----------------------- [Section titled “Tune your startup flags”](https://docs.papermc.io/velocity/tuning/#tune-your-startup-flags) We also recommend tuning your startup flags. The current recommendation is: -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:+UnlockExperimentalVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -XX:MaxInlineLevel=15 You will add these flags after the `java` command but before the `-jar` parameter. ### Explanation of the flags [Section titled “Explanation of the flags”](https://docs.papermc.io/velocity/tuning/#explanation-of-the-flags) Most of these flags focus on tuning the G1 garbage collector to be more friendly to Velocity’s workload. One of these flags (`-XX:MaxInlineLevel=15`) tends to improve performance in general. Before the release of Java 9, the default Java garbage collector was the Parallel GC. This is a stop-the-world collector that does its work in parallel. The problem is that its pause times tend to be long, and are not suitable for Minecraft (often showing up as seemingly unexplainable lag spikes). The recommended garbage collector for Velocity is the G1 region-based collector. There are several reasons for us to recommend G1: * It strikes the right balance between throughput and pause times. Throughput is roughly how much work the proxy can achieve. * It is compatible with most setups (it is available in Java 8, the earliest Java version we support). Setups using these flags tend have very low (less than 10 millisecond) GC pauses every few minutes, which is very good for Minecraft. ### Other configurations [Section titled “Other configurations”](https://docs.papermc.io/velocity/tuning/#other-configurations) Velocity is an application that tends to follow the generational hypothesis quite closely. It has also been tuned to reduce load on the garbage collector as much as possible. #### ZGC [Section titled “ZGC”](https://docs.papermc.io/velocity/tuning/#zgc) ZGC (the Z Garbage Collector), introduced with Java 11 and stabilized with Java 15, has proven to be successful for one large-scale deployment of Velocity. At its core, ZGC is a concurrent, generation-less garbage collector emphasizing low latency at the expense of throughput. Given the nature of Velocity as a network proxy where low throughput and high throughput are important, we recommend using ZGC with caution, and only if you use Java 15 or above. The primary tuning flag for ZGC is heap size - if ZGC cannot collect garbage faster than the proxy can allocate it, the threads generating garbage will be temporarily paused, causing the proxy to appear to be laggy. Our heap size recommendations still apply, but prepare to give the proxy more memory if necessary. #### Shenandoah [Section titled “Shenandoah”](https://docs.papermc.io/velocity/tuning/#shenandoah) Introduced in Java 11 and declared stable in Java 15, Shenandoah is similar to G1 in being a concurrent, generational garbage collector, but it does more work in parallel. The Velocity team is not aware of any successful deployments of Shenandoah with Velocity in the wild. #### OpenJ9 [Section titled “OpenJ9”](https://docs.papermc.io/velocity/tuning/#openj9) OpenJ9 is an alternative to the HotSpot JVM derived from IBM’s J9 JVM, focused primarily on cloud workloads. As a result, it behaves very differently from HotSpot. Correspondingly, it has a completely different set of garbage collectors. The default `gencon` garbage collector should work fine with Velocity. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Creating your first plugin | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#_top) Creating your first plugin ========================== It is very simple to create a plugin for Velocity. This section will teach you how to set up your IDE, your plugin identifiers, and give you an introduction to the basics of the Velocity API. Before you continue… -------------------- [Section titled “Before you continue…”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#before-you-continue) You will need proficiency in the Java programming language. If you don’t know Java yet, we strongly recommend you learn some basic Java before you continue. Set up your environment ----------------------- [Section titled “Set up your environment”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#set-up-your-environment) You’re going to need the [JDK](https://docs.papermc.io/misc/java-install) and an IDE. If you don’t have an IDE, IntelliJ IDEA is recommended. Creating the project in your IDE -------------------------------- [Section titled “Creating the project in your IDE”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#creating-the-project-in-your-ide) * Open your IDE * Click `Create New Project` or the equivalent * Select either `Gradle` or `Maven` * Make sure your **Project JDK** is Java 21 or later * **Finish** the dialog and open the project. Now we have created our project, we need configure our build system. I know how to do this. Give me what I need! ------------------------------------------- [Section titled “I know how to do this. Give me what I need!”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#i-know-how-to-do-this-give-me-what-i-need) ### Maven repository [Section titled “Maven repository”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#maven-repository) | Name | URL | | --- | --- | | `papermc` | `https://repo.papermc.io/repository/maven-public/` | ### Dependency [Section titled “Dependency”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#dependency) | Group ID | Artifact ID | Version | | --- | --- | --- | | `com.velocitypowered` | `velocity-api` | 3.5.0-SNAPSHOT | ### Javadocs [Section titled “Javadocs”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#javadocs) Javadocs are available at [jd.papermc.io](https://jd.papermc.io/velocity) . Set up your build system ------------------------ [Section titled “Set up your build system”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#set-up-your-build-system) You will need to set up a build system before you continue. While it is possible to write Velocity plugins without one, having a build system will make your life a lot less difficult. How to set up a build system is outside the scope of this page, but you can look at your build system’s documentation ([Gradle](https://docs.gradle.org/current/userguide/userguide.html) or [Maven](https://maven.apache.org/guides/getting-started/index.html) ) for assistance. ### Setting up the dependency [Section titled “Setting up the dependency”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#setting-up-the-dependency) * [Gradle (Kotlin)](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#tab-panel-79) * [Gradle (Groovy)](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#tab-panel-80) * [Maven 4+](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#tab-panel-81) * [Maven 3](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#tab-panel-82) repositories { maven { name = "papermc" url = uri("https://repo.papermc.io/repository/maven-public/") }} dependencies { compileOnly("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT") annotationProcessor("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT")} repositories { maven { name = 'papermc' url = 'https://repo.papermc.io/repository/maven-public/' }} dependencies { compileOnly 'com.velocitypowered:velocity-api:3.5.0-SNAPSHOT' annotationProcessor 'com.velocitypowered:velocity-api:3.5.0-SNAPSHOT'} papermc https://repo.papermc.io/repository/maven-public/ com.velocitypowered velocity-api 3.5.0-SNAPSHOT provided com.velocitypowered velocity-api 3.5.0-SNAPSHOT processor papermc https://repo.papermc.io/repository/maven-public/ com.velocitypowered velocity-api 3.5.0-SNAPSHOT provided org.apache.maven.plugins maven-compiler-plugin com.velocitypowered velocity-api 3.5.0-SNAPSHOT Using the Minecraft Development IntelliJ plugin ----------------------------------------------- [Section titled “Using the Minecraft Development IntelliJ plugin”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#using-the-minecraft-development-intellij-plugin) Alternatively, you can use the [Minecraft Development IntelliJ plugin](https://plugins.jetbrains.com/plugin/8327-minecraft-development) to create a new project. To do that you need to install the plugin first. ### Installing the Minecraft Development plugin [Section titled “Installing the Minecraft Development plugin”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#installing-the-minecraft-development-plugin) The first thing you need to do is install the [Minecraft Development](https://plugins.jetbrains.com/plugin/8327-minecraft-development) plugin. You can do this by going to `File > Settings > Plugins` and searching for `Minecraft Development` under the `Marketplace` section. ![](https://docs.papermc.io/_astro/installing-plugin.C20qTP_2_Z2kmJD3.webp) Once you have installed the plugin, you will need to restart IntelliJ. To do that you can click the `Restart IDE` button that appears after installing the plugin. ![](https://docs.papermc.io/_astro/restart-ide.F2xwJWmT_ZN6Q1k.webp) ### Creating a new project [Section titled “Creating a new project”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#creating-a-new-project) Now that you have installed the plugin, you can create a new project by going to `File > New > Project...` and selecting `Minecraft` from the list of options. ### Setting up a Velocity project [Section titled “Setting up a Velocity project”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#setting-up-a-velocity-project) ![](https://docs.papermc.io/_astro/new-project-velocity.bIF006Sa_Z1uWhYG.webp) You will be asked to provide some information about your project. | Field | Explanation | | --- | --- | | **Name** | The name of your project. | | **Location** | The location of your project. This is where the project files will be stored. | | **Platform Type** | The platform type you are developing for. This should be `Plugin`. | | **Platform** | The platform you are developing for. This should be `Velocity`. | | **Velocity Version** | The version of Velocity you are developing for. | | **Plugin Id** | The id of your plugin. | | **Plugin Name** | The name of your plugin. | | **Main Class** | The main class of your plugin. This class should have the `@Plugin` annotation. | | **Optional Setting** | Here you can define things like authors, website, description, etc. These are optional and not required for the plugin to work. | | **Build System** | The build system you want to use. Paper recommends using Gradle but you can use Maven if you prefer. | | **Group ID** | The group ID of your project. This is used for Maven and Gradle. This is usually your domain name in reverse. If you don’t know what you should put here, you can use something like `io.github.` or if you don’t have GitHub you can just use `me.`. | | **Artifact ID** | The artifact ID of your project. This is used for Maven and Gradle. This is usually the name of your project. This is usually the same as the `Name` field. | | **Version** | The version of your project. This is used for Maven and Gradle. This is usually `1.0-SNAPSHOT` and does not really matter for now. | | **JDK** | The JDK you want to use. This can be anything from Java 21 and above. | Now you can click on the `Create` button and IntelliJ will create the project for you. If everything went well, you should see something like this: ![](https://docs.papermc.io/_astro/velocity-plugin-overview.DeDZ0A7Q_1ESKxK.webp) Conclusion ---------- [Section titled “Conclusion”](https://docs.papermc.io/velocity/dev/creating-your-first-plugin/#conclusion) You should now have a project set up with Velocity as a dependency. All you have left to do now is to compile your plugin and run it on a Velocity server. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Development | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/dev/#_top) Development =========== Welcome to the Velocity development guide! This guide includes information and tutorials for developers to create and expand on Velocity plugins. #### Getting started [Section titled “Getting started”](https://docs.papermc.io/velocity/dev/#getting-started) [Creating your first plugin](https://docs.papermc.io/velocity/dev/creating-your-first-plugin) How to create your first plugin with the Velocity API. [Velocity plugin basics](https://docs.papermc.io/velocity/dev/api-basics) How to get started with the Velocity API. [Common pitfalls](https://docs.papermc.io/velocity/dev/pitfalls) How to avoid common pitfalls within Velocity. #### How-to guides [Section titled “How-to guides”](https://docs.papermc.io/velocity/dev/#how-to-guides) [Dependency management](https://docs.papermc.io/velocity/dev/dependency-management) How to handle dependencies within your Velocity plugin. [Porting your plugin from Velocity 1.x.x](https://docs.papermc.io/velocity/dev/porting-plugins-from-velocity-1) How to port your plugin from Velocity 1.x.x to modern API. #### API [Section titled “API”](https://docs.papermc.io/velocity/dev/#api) [Working with events](https://docs.papermc.io/velocity/dev/event-api) How to listen for events in Velocity. [Using the scheduler](https://docs.papermc.io/velocity/dev/scheduler-api) A guide to the Scheduler API within Velocity allowing tasks to be run. [Command API](https://docs.papermc.io/velocity/dev/command-api) How to create commands within Velocity. [Plugin messaging](https://docs.papermc.io/velocity/dev/plugin-messaging) How to handle and send plugin messages on Velocity. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Getting started | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/getting-started/#_top) Getting started =============== This page covers how to install and set up a minimal configuration of Velocity. Installing Java --------------- [Section titled “Installing Java”](https://docs.papermc.io/velocity/getting-started/#installing-java) Velocity is written in Java, so if you do not already have Java installed, you will need to install it before you continue. Velocity requires at least Java 21. See our [Java installation guide](https://docs.papermc.io/misc/java-install) for detailed instructions. Downloading Velocity -------------------- [Section titled “Downloading Velocity”](https://docs.papermc.io/velocity/getting-started/#downloading-velocity) Head over to the [downloads](https://papermc.io/downloads/velocity) page to get the latest version of Velocity. We recommend getting the latest stable version. After downloading Velocity, move the JAR file to a dedicated folder for just the proxy or upload it to your server. Launching Velocity for the first time ------------------------------------- [Section titled “Launching Velocity for the first time”](https://docs.papermc.io/velocity/getting-started/#launching-velocity-for-the-first-time) Once you have downloaded Velocity, we will launch it for the first time to generate the configuration file, `velocity.toml`. You can use the start script created to launch Velocity once you’re done configuring Velocity. ### Launching Velocity under Windows [Section titled “Launching Velocity under Windows”](https://docs.papermc.io/velocity/getting-started/#launching-velocity-under-windows) Create a `start.bat` with the following contents in the same directory where you intend to place the proxy files. @echo offjava -Xms1G -Xmx1G -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:+UnlockExperimentalVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -XX:MaxInlineLevel=15 -jar velocity.jarpause Once saved, double-click the `start.bat` file. If it worked, you should now receive a console similar to the output in the next section. ### Launching Velocity under macOS or Linux [Section titled “Launching Velocity under macOS or Linux”](https://docs.papermc.io/velocity/getting-started/#launching-velocity-under-macos-or-linux) Create a `start.sh` with the following contents in the same directory where you intend to place the proxy files. You may do this using a file transfer client, or using a text editor running on the host. #!/bin/sh java -Xms1G -Xmx1G -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:+UnlockExperimentalVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -XX:MaxInlineLevel=15 -jar velocity*.jar Once you’ve saved the files, open a terminal (or log into the machine) if you haven’t already. Navigate to the directory where you have placed the Velocity JAR file and the `start.sh` file. Then, you will need to prepare the `start.sh` script for it to be executable and run it. 1. Run `chmod u+x start.sh`. This command modifies the file’s permissions, granting the file’s owner (you) the ability to execute (`x`) the script. Without this step, the system may not recognize the script as something that can be run. 2. Now that the file is executable, run `./start.sh` to run the script. After launch ------------ [Section titled “After launch”](https://docs.papermc.io/velocity/getting-started/#after-launch) Here’s a sample of what you’ll see once we’ve started the proxy: [05:41:13 INFO]: Booting up Velocity 3.5.0-SNAPSHOT (git-74c932e5-b363)...[05:41:13 INFO]: Loading localizations...[05:41:13 INFO]: Connections will use epoll channels, libdeflate (Linux aarch64) compression, OpenSSL (Linux aarch64) ciphers[05:41:13 INFO]: Loading plugins...[05:41:13 INFO]: Loaded 0 plugins[05:41:13 INFO]: Listening on /[0:0:0:0:0:0:0:0%0]:25565[05:41:13 INFO]: Done (0.36s)! Velocity has launched, and you are now ready to configure the proxy completely. Go ahead and type `end` at the console and press enter. The proxy will shut down: > end[05:42:10 INFO]: Shutting down the proxy...[05:42:10 INFO]: Closing endpoint /0.0.0.0:25565 If you used the Windows batch script from earlier, the window will ask you to press a key. You can either press a key or close the command window. ### Configuring your servers [Section titled “Configuring your servers”](https://docs.papermc.io/velocity/getting-started/#configuring-your-servers) We now need to configure each server to accept connections from the proxy. Velocity is a highly configurable proxy. While most users will not need to change everything in the config, there are tons of options covered [on the configuration reference page](https://docs.papermc.io/velocity/configuration) along with an explanation on how each option works. However, in this section we will do the bare minimum to get the proxy up and running. Open the `velocity.toml` file in a text editor and search for the `[servers]` section. This section specifies the servers that Velocity can connect to. Here’s what the `[servers]` section will look like initially: [servers]# Configure your servers here. Each key represents the server's name, and the value# represents the IP address of the server to connect to.lobby = "127.0.0.1:30066"factions = "127.0.0.1:30067"minigames = "127.0.0.1:30068" # In what order we should try servers when a player logs in or is kicked from a server.try = [ "lobby", "factions"] On the left side, you will specify a name for the server (for example, `lobby`) and on right is a string indicating the IP address and port for the server. You will now need to add your servers to the list. You can change the list of servers as needed. The `try` setting is special. It is a list of servers Velocity should try to connect the player to when the player first logs onto the proxy or gets kicked from a server. If you decided to change the name of the `lobby` server, then you should replace `lobby` in this list with the name you chose for the first server the player should log into first. Open the `server.properties` file for each of your servers and set the `online-mode` setting to `false`. This allows Velocity to connect to your server. Once you’re done, restart your server. While Velocity is now ready for use, you will almost certainly want to [secure your servers](https://docs.papermc.io/velocity/security) and [configure player information forwarding](https://docs.papermc.io/velocity/player-information-forwarding) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Administration | PaperMC Docs [Skip to content](https://docs.papermc.io/velocity/admin/#_top) Administration ============== Welcome to the Velocity administration guide! This guide includes information and tutorials regarding the administration of a Velocity proxy. #### Getting started [Section titled “Getting started”](https://docs.papermc.io/velocity/admin/#getting-started) [Getting started](https://docs.papermc.io/velocity/getting-started) How to install and set up a minimal configuration of Velocity. [What does Velocity do for me?](https://docs.papermc.io/velocity/why-velocity) An explanation for why you should run Velocity. [Configuring player information forwarding](https://docs.papermc.io/velocity/player-information-forwarding) How to configure information forwarding on Velocity. [Frequently asked questions](https://docs.papermc.io/velocity/faq) Frequently asked Velocity administration questions. #### How-to guides [Section titled “How-to guides”](https://docs.papermc.io/velocity/admin/#how-to-guides) [Tuning Velocity](https://docs.papermc.io/velocity/tuning) How to tune Velocity to allow for even better performance. [Securing your servers](https://docs.papermc.io/velocity/security) An explanation of how to secure your servers. [Migration guide](https://docs.papermc.io/velocity/migration) How to migrate your proxy between different Velocity versions. #### Reference [Section titled “Reference”](https://docs.papermc.io/velocity/admin/#reference) [Configuring Velocity](https://docs.papermc.io/velocity/configuration) Velocity is designed to be easy to configure and this guide will walk you through how to do so. [System properties](https://docs.papermc.io/velocity/reference/system-properties) Documentation for the system properties and environment variables Velocity may check. [Built-in commands](https://docs.papermc.io/velocity/built-in-commands) A list of the built-in commands with explanations. [Server compatibility](https://docs.papermc.io/velocity/server-compatibility) A guide to the server compatibility for Velocity. [Comparing with other proxies](https://docs.papermc.io/velocity/comparisons-to-other-proxies) A comparison of Velocity to other proxies. [Libraries used](https://docs.papermc.io/velocity/credits) The credits for all the different libraries used by Velocity. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Events | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/contributing/events/#_top) Events ====== There are several requirements for events in the Paper API. All new events should go in the package (sub-package of) `io.papermc.paper.event`. ### Constructors [Section titled “Constructors”](https://docs.papermc.io/paper/contributing/events/#constructors) All new constructors added should be annotated with [`@ApiStatus.Internal`](https://javadoc.io/doc/org.jetbrains/annotations/latest/org/jetbrains/annotations/ApiStatus.Internal.html) to signify that they are not considered API and can change at any time without warning. Constructors that are being replaced, if they aren’t being removed, should be marked with [`@Deprecated`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Deprecated.html) and [`@DoNotUse`](https://jd.papermc.io/paper/io/papermc/paper/annotation/DoNotUse.html) . ### Mutability [Section titled “Mutability”](https://docs.papermc.io/paper/contributing/events/#mutability) Certain API types are “mutable” which can lead to unexpected behavior within events. Mutable types like [`Location`](https://jd.papermc.io/paper/org/bukkit/Location.html) and [`Vector`](https://jd.papermc.io/paper/org/bukkit/util/Vector.html) should therefore be cloned when returned from a “getter” in an event. ### `HandlerList` [Section titled “HandlerList”](https://docs.papermc.io/paper/contributing/events/#handlerlist) For an event class or any subclass of it to be listened to, a [`HandlerList`](https://jd.papermc.io/paper/org/bukkit/event/HandlerList.html) field must be present with an instance and static method to retrieve it. See the docs for [`Event`](https://jd.papermc.io/paper/org/bukkit/event/Event.html) for specifics. This field should be static and final and named `HANDLER_LIST`. Also consider not putting a `HandlerList` on every event, just a “common parent” event so that a plugin can listen to the parent event and capture any child events but also listen to the child event separately. ### Miscellaneous [Section titled “Miscellaneous”](https://docs.papermc.io/paper/contributing/events/#miscellaneous) * New parameters or method returns of type [`ItemStack`](https://jd.papermc.io/paper/org/bukkit/inventory/ItemStack.html) should not be [`@Nullable`](https://javadoc.io/doc/org.jspecify/jspecify/latest/org/jspecify/annotations/Nullable.html) in most case and instead accept an empty itemStack. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Contributing | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/contributing/#_top) Contributing ============ Welcome to the Paper contributing guide! This guide includes information and tutorials for developers wishing to contribute to the Paper project. [Events](https://docs.papermc.io/paper/contributing/events) A guide on how to add new events to Paper. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Adding plugins | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/adding-plugins/#_top) Adding plugins ============== Plugins are the most powerful way to extend the functionality of Paper beyond the configuration files. Functionality added by plugins can range from making milk restore hunger or dead bushes grow, to adding entirely new and original game modes or items. Finding plugins --------------- [Section titled “Finding plugins”](https://docs.papermc.io/paper/adding-plugins/#finding-plugins) Before installing a plugin, you’ll need to find what you want to install. The best place to find plugins is [Hangar](https://hangar.papermc.io/) , Paper’s plugin repository, but you can also find plugins on [Modrinth](https://modrinth.com/discover/plugins?g=categories:paper) or [BukkitDev](https://dev.bukkit.org/bukkit-plugins) . Many plugins may release on [GitHub](https://github.com/) . Instead of checking each site directly, you can also use a search engine. Searching for the function you desire, followed by `Paper plugin` will often yield good results. Installing plugins ------------------ [Section titled “Installing plugins”](https://docs.papermc.io/paper/adding-plugins/#installing-plugins) 1. Once you’ve found the plugin you’d like to install, download it. Ensure the file you have downloaded ends in `.jar`. Some plugins also distribute as `.zip` files, in which case you will need to extract the file and locate the `.jar` for your platform, often labeled `bukkit` or `paper`. 2. Once you have the plugin downloaded locally, locate the `plugins` folder from the root directory of your Paper server. 3. Drag and drop the plugin file (`.jar`) into the `plugins` folder. If you are using a shared hosting service, you may need to use their web panel or SFTP to upload the plugin; however, the procedure will be the same. 4. Restart your server. The plugin should load. 5. Check your work. Once the server has finished loading, run the `/plugins` command in-game or type `plugins` into the console. You should see your freshly installed plugin listed in green. If it is not listed or is colored red, continue to [troubleshooting](https://docs.papermc.io/paper/adding-plugins/#troubleshooting) . A plugin listed in red means that it is not currently enabled. For a freshly installed plugin, this often means that the plugin failed to load. Troubleshooting --------------- [Section titled “Troubleshooting”](https://docs.papermc.io/paper/adding-plugins/#troubleshooting) ### Check your logs [Section titled “Check your logs”](https://docs.papermc.io/paper/adding-plugins/#check-your-logs) The first step to troubleshooting installing plugins is to check the log of your server. Your server’s most recent logs will be stored to the `logs/latest.log` file. You may need to scroll near the beginning of this file to see when plugins were loaded. #### Missing dependencies [Section titled “Missing dependencies”](https://docs.papermc.io/paper/adding-plugins/#missing-dependencies) If you see something like this: [00:00:00] [Server thread/WARN] Could not load 'plugins/MyAwesomePlugin-1.0.0.jar' in folder 'plugins'[00:00:00] [Server thread/WARN] org.bukkit.plugin.UnknownDependencyException: Unknown/missing dependency plugins: [Vault]. Please download and install these plugins to run 'MyAwesomePlugin'. This means that the plugin you tried to install is missing a dependency. A dependency, in this case, is another plugin that you must install for the first to function. While you will get a big scary error, the important line to look at is: [00:00:00] [Server thread/WARN] Unknown/missing dependency plugins: [Vault]. Please download and install these plugins to run 'MyAwesomePlugin'. This is telling you that in order to load `MyAwesomePlugin`, you must first install `Vault`. #### Invalid `plugin.yml` [Section titled “Invalid plugin.yml”](https://docs.papermc.io/paper/adding-plugins/#invalid-pluginyml) If you see something closer to this: [00:00:00] [Server thread/WARN] Could not load 'plugins/MyAwesomePlugin-1.0.0.jar' in folder 'plugins'[00:00:00] [Server thread/WARN] org.bukkit.plugin.InvalidDescriptionException: Invalid plugin.yml This means that what you have downloaded isn’t a valid Paper plugin. This is generally caused by one of the following: 1. The plugin you downloaded isn’t a plugin at all, but instead a mod for Forge, Fabric, or similar. These will not run on Paper. 2. The plugin failed to download completely. Especially when using tools such as `curl` or `wget`, you can easily download error pages rather than the plugin you intended. This may also be caused by a network issue. Attempt to download the plugin again. If you are using FTP (not SFTP or a web panel) to upload your plugin to a shared hosting service, ensure your FTP client is in `binary` and not `ASCII` mode. Consult the documentation for your FTP client for details. #### Ambiguous plugin name [Section titled “Ambiguous plugin name”](https://docs.papermc.io/paper/adding-plugins/#ambiguous-plugin-name) If you see something like this: [00:00:00] [Server thread/WARN] Ambiguous plugin name `Essentials' for files `plugins/EssentialsX-2.19.4.jar' and `plugins/Essentialsx-2.20.0-dev.jar' in `plugins' This means you have two plugins with the same name, which is not supported. In this case, two versions of EssentialsX are installed. Both the release `2.19.4`, and a development build of `2.20.0`. Ensure you only have one version of each plugin installed at one time. Delete the older version of the duplicate plugin, and restart your server. To prevent accidentally installing two versions of one plugin while updating, you can use the `update` folder as described in the [Update Guide](https://docs.papermc.io/paper/updating#step-2-update-plugins) . #### Something else [Section titled “Something else”](https://docs.papermc.io/paper/adding-plugins/#something-else) If you see an error, but it isn’t similar to one of the above, attempt to read it yourself. While the full error may be large and scary, you likely only have to read the first one or two lines to understand what is going on. If you’re not sure, do not hesitate to reach out for support on our [Discord](https://discord.gg/papermc) in the `#paper-help` channel. ### If nothing is logged [Section titled “If nothing is logged”](https://docs.papermc.io/paper/adding-plugins/#if-nothing-is-logged) If nothing is logged, your server is likely not attempting to load any plugins. The conditions needed for the server to load a plugin are as follows: 1. The file is at the root of the `plugins` folder, relative to its working directory. This is usually the same folder as the server JAR file. **Subdirectories of the `plugins` folder will not be checked.** All plugins must be in the root folder. 2. The file ends in `.jar`. If your plugin does not end in `.jar`, what you have downloaded may not be a plugin. Note that some plugins distribute multiple JARs as `.zip` files. If this is the case, you have to extract them before installing the plugin. If both of these are true, and you still see no logs, please reach out for support on our [Discord](https://discord.gg/papermc) server in the `#paper-help` channel. We will be happy to assist you. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Miscellaneous | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/admin/misc/#_top) Miscellaneous ============= Miscellaneous documentation pertaining to Paper. [Update checker](https://docs.papermc.io/paper/misc/update-checker) Documentation for Paper's built-in automatic update checker. [Bug fixes](https://docs.papermc.io/paper/misc/paper-bug-fixes) An explanation of which Vanilla bugs we fix in Paper. [Frequently asked questions](https://docs.papermc.io/paper/faq) Questions frequently asked by our community, answered by us! Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Miscellaneous | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/api/command-api/misc/#_top) Miscellaneous ============= [Basic commands](https://docs.papermc.io/paper/dev/command-api/misc/basic-command) An overview of a Bukkit-style command declaration using Brigadier. [Comparison](https://docs.papermc.io/paper/dev/command-api/misc/comparison-bukkit-brigadier) A comparison between Brigadier and Bukkit commands. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Getting started | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/admin/getting-started/#_top) Getting started =============== Guides for getting started with running a Paper server. [Getting started](https://docs.papermc.io/paper/getting-started) How to get started with downloading and setting up a Paper server. [Adding plugins](https://docs.papermc.io/paper/adding-plugins) Plugins are the most powerful way to extend the functionality of Paper beyond the configuration files. [Migrating to or from Paper](https://docs.papermc.io/paper/migration) It's simple to migrate your server to or from Paper. This page will help you get started. [Next steps](https://docs.papermc.io/paper/next-steps) How to proceed after starting your server. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Inventories | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/api/inventories/#_top) Inventories =========== [Menu Type API](https://docs.papermc.io/paper/dev/menu-type-api) A guide to the Menu Type API. [Custom InventoryHolders](https://docs.papermc.io/paper/dev/custom-inventory-holder) How to use a custom InventoryHolder to identify custom inventories. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Lifecycle API | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/api/lifecycle/#_top) Lifecycle API ============= [Lifecycle API](https://docs.papermc.io/paper/dev/lifecycle) An introduction to Paper's Lifecycle API. [Datapack discovery](https://docs.papermc.io/paper/dev/lifecycle/datapacks) A guide to including datapacks in your plugin and registering them with the lifecycle API. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # How-to guides | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/admin/how-to/#_top) How-to guides ============= How-to guides for setting up specific features of Paper and managing the server. [Aikar's flags](https://docs.papermc.io/paper/aikars-flags) Aikar's flags are a set of JVM flags designed to improve the performance of your Paper server. [Configuring Anti-Xray](https://docs.papermc.io/paper/anti-xray) Paper ships an obfuscation-based Anti-Xray system by default. Learn how to configure it here. [Basic troubleshooting](https://docs.papermc.io/paper/basic-troubleshooting) This guide will help you diagnose your server's problem before reporting it to PaperMC or the plugin's author. [Profiling](https://docs.papermc.io/paper/profiling) How to profile your Paper server. [Updating](https://docs.papermc.io/paper/updating) Paper has new features and fixes coming every day, this guide explains the updating process. [Vanilla-like experience](https://docs.papermc.io/paper/vanilla) This page lists all changes that result in a different experience than Vanilla. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Component API | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/api/component-api/#_top) Component API ============= [Introduction](https://docs.papermc.io/paper/dev/component-api/introduction) An introduction to how components work. [Internationalization](https://docs.papermc.io/paper/dev/component-api/i18n) How to use Adventure's internationalization. [Audiences](https://docs.papermc.io/paper/dev/component-api/audiences) How to use Adventure's Audiences. [Signed messages](https://docs.papermc.io/paper/dev/component-api/signed-messages) A guide to working with SignedMessage objects. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Minecraft-specific | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/arguments/minecraft/#_top) Minecraft-specific ================== The [Arguments and Literals](https://docs.papermc.io/paper/dev/command-api/basics/arguments-and-literals) page covers the most used, native Brigadier arguments. But Minecraft (and Paper) define a few more. These can be accessed in a static context using the [`ArgumentTypes`](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/ArgumentTypes.html) class. We will go over all of those in this section. Quick overview -------------- [Section titled “Quick overview”](https://docs.papermc.io/paper/dev/command-api/arguments/minecraft/#quick-overview) A quick overview of all possible arguments is defined here: | Method Name | Return Value | Quick Link | | --- | --- | --- | | `blockPosition()` | [BlockPositionResolver](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/BlockPositionResolver.html) | [Block Position Argument](https://docs.papermc.io/paper/dev/command-api/arguments/location#block-position-argument) | | `blockState()` | [BlockState](https://jd.papermc.io/paper/org/bukkit/block/BlockState.html) | [Block State Argument](https://docs.papermc.io/paper/dev/command-api/arguments/paper#block-state-argument) | | `component()` | [Component (Kyori)](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/Component.html) | [Component Argument](https://docs.papermc.io/paper/dev/command-api/arguments/adventure#component-argument) | | `doubleRange()` | [DoubleRangeProvider](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/range/DoubleRangeProvider.html) | [Double Range argument](https://docs.papermc.io/paper/dev/command-api/arguments/predicate#double-range-argument) | | `entity()` | [EntitySelectorArgumentResolver](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/selector/EntitySelectorArgumentResolver.html) | [Entity Argument](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player#entity-argument) | | `entities()` | [EntitySelectorArgumentResolver](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/selector/EntitySelectorArgumentResolver.html) | [Entities Argument](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player#entities-argument) | | `entityAnchor()` | [LookAnchor](https://jd.papermc.io/paper/io/papermc/paper/entity/LookAnchor.html) | [Entity Anchor Argument](https://docs.papermc.io/paper/dev/command-api/arguments/enums#entity-anchor-argument) | | `finePosition(boolean centerIntegers)` | [FinePositionResolver](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/FinePositionResolver.html) | [Fine Position Argument](https://docs.papermc.io/paper/dev/command-api/arguments/location#fine-position-argument) | | `gameMode()` | [GameMode](https://jd.papermc.io/paper/org/bukkit/GameMode.html) | [GameMode Argument](https://docs.papermc.io/paper/dev/command-api/arguments/enums#gamemode-argument) | | `heightMap()` | [HeightMap](https://jd.papermc.io/paper/org/bukkit/HeightMap.html) | [HeightMap Argument](https://docs.papermc.io/paper/dev/command-api/arguments/enums#heightmap-argument) | | `integerRange()` | [IntegerRangeProvider](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/range/IntegerRangeProvider.html) | [Integer Range Argument](https://docs.papermc.io/paper/dev/command-api/arguments/predicate#integer-range-argument) | | `itemPredicate()` | [ItemStackPredicate](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/predicate/ItemStackPredicate.html) | [Item Predicate Argument](https://docs.papermc.io/paper/dev/command-api/arguments/predicate#item-predicate-argument) | | `itemStack()` | [ItemStack](https://jd.papermc.io/paper/org/bukkit/inventory/ItemStack.html) | [ItemStack Argument](https://docs.papermc.io/paper/dev/command-api/arguments/paper#itemstack-argument) | | `key()` | [Key (Kyori)](https://jd.advntr.dev/key/latest/net/kyori/adventure/key/Key.html) | [Key Argument](https://docs.papermc.io/paper/dev/command-api/arguments/adventure#key-argument) | | `namedColor()` | [NamedTextColor (Kyori)](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/format/NamedTextColor.html) | [Named Color Argument](https://docs.papermc.io/paper/dev/command-api/arguments/adventure#named-color-argument) | | `namespacedKey()` | [NamespacedKey](https://jd.papermc.io/paper/org/bukkit/NamespacedKey.html) | [Bukkit NamespacedKey Argument](https://docs.papermc.io/paper/dev/command-api/arguments/paper#namespacedkey-argument) | | `objectiveCriteria()` | [Criteria](https://jd.papermc.io/paper/org/bukkit/scoreboard/Criteria.html) | [Objective Criteria Argument](https://docs.papermc.io/paper/dev/command-api/arguments/paper#objective-criteria-argument) | | `player()` | [PlayerSelectorArgumentResolver](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/selector/PlayerSelectorArgumentResolver.html) | [Player Argument](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player#player-argument) | | `players()` | [PlayerSelectorArgumentResolver](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/selector/PlayerSelectorArgumentResolver.html) | [Players Argument](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player#players-argument) | | `playerProfiles()` | [PlayerProfileListResolver](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/PlayerProfileListResolver.html) | [Player Profiles Argument](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player#player-profiles-argument) | | `resource(RegistryKey)` | (Depends on RegistryKey) | [Resource Argument](https://docs.papermc.io/paper/dev/command-api/arguments/registry#resource-argument) | | `resourceKey(RegistryKey)` | (Depends on RegistryKey) | [Resource Key Argument](https://docs.papermc.io/paper/dev/command-api/arguments/registry#resource-key-argument) | | `style()` | [Style (Kyori)](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/format/Style.html) | [Style Argument](https://docs.papermc.io/paper/dev/command-api/arguments/adventure#adventure-style-argument) | | `signedMessage()` | [SignedMessageResolver](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/SignedMessageResolver.html) | [Signed Message Argument](https://docs.papermc.io/paper/dev/command-api/arguments/adventure#signed-message-argument) | | `scoreboardDisplaySlot()` | [DisplaySlot](https://jd.papermc.io/paper/org/bukkit/scoreboard/DisplaySlot.html) | [Scoreboard Display Slot Argument](https://docs.papermc.io/paper/dev/command-api/arguments/enums#scoreboard-display-slot-argument) | | `time(int mintime)` | Integer | [Time Argument](https://docs.papermc.io/paper/dev/command-api/arguments/paper#time-argument) | | `templateMirror()` | [Mirror](https://jd.papermc.io/paper/org/bukkit/block/structure/Mirror.html) | [Template Mirror Argument](https://docs.papermc.io/paper/dev/command-api/arguments/enums#template-mirror-argument) | | `templateRotation()` | [StructureRotation](https://jd.papermc.io/paper/org/bukkit/block/structure/StructureRotation.html) | [Template Rotation Argument](https://docs.papermc.io/paper/dev/command-api/arguments/enums#template-rotation-argument) | | `uuid()` | UUID | [UUID Argument](https://docs.papermc.io/paper/dev/command-api/arguments/paper#uuid-argument) | | `world()` | [World](https://jd.papermc.io/paper/org/bukkit/World.html) | [World Argument](https://docs.papermc.io/paper/dev/command-api/arguments/location#world-argument) | Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Aikar's flags | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/aikars-flags/#_top) Aikar's flags ============= Recommended JVM startup flags ----------------------------- [Section titled “Recommended JVM startup flags”](https://docs.papermc.io/paper/aikars-flags/#recommended-jvm-startup-flags) java -Xms10G -Xmx10G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -jar paper.jar --nogui Recommended memory ------------------ [Section titled “Recommended memory”](https://docs.papermc.io/paper/aikars-flags/#recommended-memory) **We recommend using at least 6-10GB**, no matter how few players! If you can’t afford 10GB of memory, give as much as you can, but ensure you leave the operating system some memory too. G1GC operates better with more memory. However, more memory does not mean better performance above a certain point. Eventually you will hit a point of diminishing returns. Going out and getting 32GB of RAM for a server will only waste your money with minimal returns. Java GC logging --------------- [Section titled “Java GC logging”](https://docs.papermc.io/paper/aikars-flags/#java-gc-logging) Are you having old gen issues with these flags? Add the following flags based on your Java version to enable GC logging: **Java 8-10** -Xloggc:gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=1M **Java 11+** -Xlog:gc*:logs/gc.log:time,uptime:filecount=5,filesize=1M GC logging does not hurt your performance and can be left on at all times. The files will not take up much space (5MB) Technical explanation of the flags ---------------------------------- [Section titled “Technical explanation of the flags”](https://docs.papermc.io/paper/aikars-flags/#technical-explanation-of-the-flags) 1. **\-Xms matching -Xmx - why:** You should never run your server with the case that `Xmx` can run the system completely out of memory. Your server should always be expected to use the entire `Xmx`! You should then ensure the OS has extra memory on top of that `Xmx` for non-Minecraft/OS level things. Therefore, you should never run Minecraft with `Xmx` settings you can’t support if Java uses it all. Now, that means **if `Xms` is lower than `Xmx` you have unused memory**! Unused memory is wasted memory. G1 operates better with the more memory it’s given. G1 adaptively chooses how much memory to give to each region to optimize pause time. If you have more memory than it needs to reach an optimal pause time, G1 will simply push that extra into the old generation, and it will not hurt you. The fundamental idea of improving GC behavior is to ensure short-lived objects die young and never get promoted. With the more memory G1 has, the better assurance you will get that objects are not getting prematurely promoted to the old generation. G1 operates differently than previous collectors and is able to handle larger heaps more efficiently. If it does not need the memory given to it, it will not use it. The entire engine operates differently and does not suffer from too large of heaps, and this is industry-wide accepted information that under G1 to keep Xms and Xmx the same! 2. **UnlockExperimentalVMOptions:** needed for some the below options 3. **G1NewSizePercent:** These are the important ones. You now can specify percentages of an overall desired range for the new generation. With these settings, we tell G1 to not use its default 5% for new gen, and instead give it 40%! **Minecraft has an extremely high memory allocation rate**, ranging to at least 800MB/second on a 30 player server! And this is mostly short-lived objects (Block Position). Now, this means Minecraft **really** needs more focus on new gen to be able to even support this allocation rate. If your new gen is too small, you will be running new gen collections 1-2+ times per second, which is awful. You will have so many pauses that TPS has risk of suffering, and the server will not be able to keep up with the cost of GCs. Then combine the fact that objects will now promote faster, resulting in your old gen growing faster. Given more new gen, we are able to slow down the intervals of young gen collections, resulting in more time for short-lived objects to die young and overall more efficient GC behavior. 4. **G1MixedGCLiveThresholdPercent:** Controls when to include regions in mixed GCs in the young GC collection, keeping old gen tidy without doing a normal old gen GC collection. When your memory is less than this percent, old gen won’t even be included in ‘mixed’ collections. Mixed are not as heavy as a full old collection, so having small incremental cleanups of old keeps memory usage light. Default is 65 to 85 depending on the Java version, we are setting that to 90 to ensure we reclaim garbage in old gen as fast as possible to retain as much free regions as we can. 5. **G1ReservePercent=20:** Minecraft memory allocation rate in up-to-date versions is really insane. We run the risk of a dreaded “to-space exhaustion” not having enough memory free to move data around. This ensures more memory is waiting to be used for this operation. Default is 10, so we are giving another 10 to it. 6. **MaxTenuringThreshold=1:** Minecraft has a really high allocation rate of memory. Of that memory, most is reclaimed in the eden generation. However, transient data will overflow into survivor. Initially played with completely removing survivor and had decent results, but does result in transient data making its way to old which is not good. Max Tenuring 1 ensures that we do not promote transient data to old generation, but anything that survives 2 passes of GC is just going to be assumed as longer-lived. Doing this greatly reduces pause times in young collections as copying data up to 15 times in survivor space for a tenured object really takes a lot of time for actually old memory. Ideally the GC engine would track average age for objects instead and tenure out data faster, but that is not how it works. Considering average GC rate is 10s to the upwards of minutes per young collection, this does not result in any ‘garbage’ being promoted, and just delays longer lived memory to be collected in mixed GCs. 7. **SurvivorRatio=32:** Because we drastically reduced MaxTenuringThreshold, we will be reducing use of survivor space drastically. This frees up more regions to be used by eden instead. 8. **AlwaysPreTouch:** AlwaysPreTouch gets the memory setup and reserved at process start ensuring it is contiguous, improving the efficiency of it more. This improves the operating systems memory access speed. Mandatory to use Transparent Huge Pages 9. **+DisableExplicitGC:** Many plugins think they know how to control memory, and try to invoke garbage collection. Plugins that do this trigger a full garbage collection, triggering a massive lag spike. This flag disables plugins from trying to do this, protecting you from their bad code. 10. **MaxGCPauseMillis=200:** This setting controls how much memory is used in between the minimum and maximum ranges specified for your new generation. This is a “goal” for how long you want your server to pause for collections. 200 is aiming for at most loss of 4 ticks. This will result in a short TPS drop, however the server can make up for this drop instantly, meaning it will have no meaningful impact on your TPS. 200ms is lower than players can recognize. In testing, having this value constrained to an even lower number results in G1 not recollecting memory fast enough and potentially running out of old gen triggering a full collection. Just because this number is 200 does not mean every collection will be 200. It means it can use up to 200 if it really needs it, and we need to let it do its job when there is memory to collect. 11. **+ParallelRefProcEnabled:** Optimizes the GC process to use multiple threads for weak reference checking. Not sure why this isn’t default… 12. **G1RSetUpdatingPauseTimePercent=5:** Default is 10% of time spent during pause updating RSets, reduce this to 5% to make more of it concurrent to reduce pause durations. 13. **G1MixedGCCountTarget=4:** Default is 8. Because we are aiming to collect slower, with less old gen usage, try to reclaim old gen memory faster to avoid running out of old. 14. **G1HeapRegionSize=8M+:** Default is auto calculated. Super important for Minecraft, especially 1.15, as with low memory situations, the default calculation will in most times be too low. Any memory allocation half of this size (4MB) will be treated as “Humongous” and promote straight to old generation and is harder to free. If you allow Java to use the default, you will be destroyed with a significant chunk of your memory getting treated as Humongous. 15. **+PerfDisableSharedMem:** Causes GC to write to file system which can cause major latency if disk IO is high - see [https://www.evanjones.ca/jvm-mmap-pause.html](https://www.evanjones.ca/jvm-mmap-pause.html) ### Transparent huge pages [Section titled “Transparent huge pages”](https://docs.papermc.io/paper/aikars-flags/#transparent-huge-pages) Controversial feature but may be usable if you can not configure your host for real HugeTLBFS. Try adding `-XX:+UseTransparentHugePages` but it’s extremely important you also have `AlwaysPreTouch` set. Otherwise, THP will likely hurt you. We have not measured how THP works for Minecraft or its impact with `AlwaysPreTouch`, so this section is for the advanced users who want to experiment. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Reference | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/admin/reference/#_top) Reference ========= Reference of Paper’s configuration options, system properties and other features. [🗃️ Configuration](https://docs.papermc.io/paper/reference/configuration) An overview of Paper's configuration files. [Paper plugins](https://docs.papermc.io/paper/reference/paper-plugins) A guide to the ins and outs of Paper plugins. [Commands](https://docs.papermc.io/paper/reference/commands) Documentation about all commands added by Paper. [System properties](https://docs.papermc.io/paper/reference/system-properties) Documentation for the system properties and environment variables Paper may check. [CLI Arguments](https://docs.papermc.io/paper/reference/cli-arguments) Reference for all CLI arguments Paper recognizes. [Permissions](https://docs.papermc.io/paper/reference/permissions) All permissions available in the default Paper server. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Entity API | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/api/entity-api/#_top) Entity API ========== [Teleportation](https://docs.papermc.io/paper/dev/entity-teleport) The entity teleportation API and how to use it. [Display entities](https://docs.papermc.io/paper/dev/display-entities) The display entity API and how to use it. [Mob Goal API](https://docs.papermc.io/paper/dev/mob-goals) A guide to the Mob Goal API. [Entity Pathfinder API](https://docs.papermc.io/paper/dev/entity-pathfinder) A guide to the Entity Pathfinder API. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Event API | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/api/event-api/#_top) Event API ========= [Listeners](https://docs.papermc.io/paper/dev/event-listeners) Developer guide for how to listen to the broadcasted events. [Custom events](https://docs.papermc.io/paper/dev/custom-events) A guide to show you how to add custom events to your plugin. [Handler lists](https://docs.papermc.io/paper/dev/handler-lists) An explanation to what an event's HandlerList is. [Chat events](https://docs.papermc.io/paper/dev/chat-events) An outline on AsyncChatEvent and how to handle it. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Configuring Anti-Xray | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/anti-xray/#_top) Configuring Anti-Xray ===================== > Originally written and maintained by [stonar96](https://github.com/stonar96) > . Paper includes an obfuscation-based Anti-Xray with three modes, configurable on a per world basis. This guide is a step-by-step walk-through for configuring Anti-Xray. For reference documentation, refer to the Anti-Xray section of the [Per-World Configuration Reference](https://docs.papermc.io/paper/reference/world-configuration#anticheat_anti_xray) . Anti-Xray has three different modes. `engine-mode: 1` replaces specified blocks (`hidden-blocks`) with other “fake” blocks, `stone` (`deepslate` at y < 0), `netherrack`, or `end_stone` based on the dimension. In contrast, `engine-mode: 2` will replace both `hidden-blocks` and `replacement-blocks` with randomly generated `hidden-blocks`. `engine-mode: 3` works similarly to `engine-mode: 2`, but instead of randomizing every block, it randomizes the block for each layer of a chunk. The following images[1](https://docs.papermc.io/paper/anti-xray/#user-content-fn-1) show how each mode will look for a player using Xray with the recommended configuration in both the overworld and nether. ![Overworld Anti-Xray Comparison](https://docs.papermc.io/_astro/anti-xray-overworld.CWzmAZnN_1BCGx4.webp) ![Nether Anti-Xray Comparison](https://docs.papermc.io/_astro/anti-xray-nether.CUJUpqac_Z1UbD6a.webp) Especially on the client side, `engine-mode: 1` is much less computationally intensive, while `engine-mode: 2` may better prevent Xray. With `engine-mode: 1`, only ores that are entirely covered by solid blocks will be hidden. Ores exposed to air in caves or water from a lake will not be hidden. With `engine-mode: 2`, fake ores obstruct the view of real blocks. If `air` is added to `hidden-blocks`, `engine-mode: 2` will effectively hide all ores, even those exposed to air. `engine-mode: 3` can reduce network load when joining by a factor of ~2 and helps with chunk packet compression. Recommended configuration ------------------------- [Section titled “Recommended configuration”](https://docs.papermc.io/paper/anti-xray/#recommended-configuration) The recommended configuration for `engine-mode: 1`, `engine-mode: 2` and `engine-mode: 3` is as follows: ### `engine-mode: 1` [Section titled “engine-mode: 1”](https://docs.papermc.io/paper/anti-xray/#engine-mode-1) Default World Configuration Replace the existing `anticheat.anti-xray` block in `paper-world-defaults.yml` with the following: anticheat: anti-xray: enabled: true engine-mode: 1 hidden-blocks: # There's no chance to hide dungeon chests as they are entirely surrounded by air, but buried treasures will be hidden. - chest - coal_ore - deepslate_coal_ore - copper_ore - deepslate_copper_ore - raw_copper_block - diamond_ore - deepslate_diamond_ore - emerald_ore - deepslate_emerald_ore - gold_ore - deepslate_gold_ore - iron_ore - deepslate_iron_ore - raw_iron_block - lapis_ore - deepslate_lapis_ore - redstone_ore - deepslate_redstone_ore lava-obscures: false # As of 1.18 some ores are generated much higher. # Please adjust the max-block-height setting at your own discretion. # https://minecraft.wiki/w/Ore might be helpful. max-block-height: 64 # The replacement-blocks list is not used in engine-mode: 1. Changing this will have no effect. replacement-blocks: [] update-radius: 2 use-permission: false Nether Configuration Copy and paste into your `paper-world.yml` within your nether world folder. See the [Configuration Guide](https://docs.papermc.io/paper/reference/configuration) for more information. anticheat: anti-xray: enabled: true engine-mode: 1 hidden-blocks: - ancient_debris - nether_gold_ore - nether_quartz_ore lava-obscures: false max-block-height: 128 # The replacement-blocks list is not used in engine-mode: 1. Changing this will have no effect. replacement-blocks: [] update-radius: 2 use-permission: false End Configuration Copy and paste into your `paper-world.yml` within your end world folder. See the [Configuration Guide](https://docs.papermc.io/paper/reference/configuration) for more information. anticheat: anti-xray: enabled: false ### `engine-mode: 2` [Section titled “engine-mode: 2”](https://docs.papermc.io/paper/anti-xray/#engine-mode-2) Default World Configuration Replace the existing `anticheat.anti-xray` block in `paper-world-defaults.yml` with the following: anticheat: anti-xray: enabled: true engine-mode: 2 hidden-blocks: # You can add air here such that many holes are generated. # This works well against cave finders but may cause client FPS drops for all players. - air - copper_ore - deepslate_copper_ore - raw_copper_block - diamond_ore - deepslate_diamond_ore - gold_ore - deepslate_gold_ore - iron_ore - deepslate_iron_ore - raw_iron_block - lapis_ore - deepslate_lapis_ore - redstone_ore - deepslate_redstone_ore lava-obscures: false # As of 1.18 some ores are generated much higher. # Please adjust the max-block-height setting at your own discretion. # https://minecraft.wiki/w/Ore might be helpful. max-block-height: 64 replacement-blocks: # Chest is a tile entity and can't be added to hidden-blocks in engine-mode: 2. # But adding chest here will hide buried treasures, if max-block-height is increased. - chest - amethyst_block - andesite - budding_amethyst - calcite - coal_ore - deepslate_coal_ore - deepslate - diorite - dirt - emerald_ore - deepslate_emerald_ore - granite - gravel - oak_planks - smooth_basalt - stone - tuff update-radius: 2 use-permission: false Nether Configuration Copy and paste into your `paper-world.yml` within your nether world folder. See the [Configuration Guide](https://docs.papermc.io/paper/reference/configuration) for more information. anticheat: anti-xray: enabled: true engine-mode: 2 hidden-blocks: # See note about air and possible client performance issues above. - air - ancient_debris - bone_block - glowstone - magma_block - nether_bricks - nether_gold_ore - nether_quartz_ore - polished_blackstone_bricks lava-obscures: false max-block-height: 128 replacement-blocks: - basalt - blackstone - gravel - netherrack - soul_sand - soul_soil update-radius: 2 use-permission: false End Configuration Copy and paste into your `paper-world.yml` within your end world folder. See the [Configuration Guide](https://docs.papermc.io/paper/reference/configuration) for more information. anticheat: anti-xray: enabled: false ### `engine-mode: 3` [Section titled “engine-mode: 3”](https://docs.papermc.io/paper/anti-xray/#engine-mode-3) Default World Configuration Replace the existing `anticheat.anti-xray` block in `paper-world-defaults.yml` with the following: anticheat: anti-xray: enabled: true engine-mode: 3 hidden-blocks: # You can add air here such that many holes are generated. # This works well against cave finders but may cause client FPS drops for all players. - air - copper_ore - deepslate_copper_ore - raw_copper_block - diamond_ore - deepslate_diamond_ore - gold_ore - deepslate_gold_ore - iron_ore - deepslate_iron_ore - raw_iron_block - lapis_ore - deepslate_lapis_ore - redstone_ore - deepslate_redstone_ore lava-obscures: false # As of 1.18 some ores are generated much higher. # Please adjust the max-block-height setting at your own discretion. # https://minecraft.wiki/w/Ore might be helpful. max-block-height: 64 replacement-blocks: # Chest is a tile entity and can't be added to hidden-blocks in engine-mode: 2. # But adding chest here will hide buried treasures, if max-block-height is increased. - chest - amethyst_block - andesite - budding_amethyst - calcite - coal_ore - deepslate_coal_ore - deepslate - diorite - dirt - emerald_ore - deepslate_emerald_ore - granite - gravel - oak_planks - smooth_basalt - stone - tuff update-radius: 2 use-permission: false Nether Configuration Copy and paste into your `paper-world.yml` within your nether world folder. See the [Configuration Guide](https://docs.papermc.io/paper/reference/configuration) for more information. anticheat: anti-xray: enabled: true engine-mode: 3 hidden-blocks: # See note about air and possible client performance issues above. - air - ancient_debris - bone_block - glowstone - magma_block - nether_bricks - nether_gold_ore - nether_quartz_ore - polished_blackstone_bricks lava-obscures: false max-block-height: 128 replacement-blocks: - basalt - blackstone - gravel - netherrack - soul_sand - soul_soil update-radius: 2 use-permission: false End Configuration Copy and paste into your `paper-world.yml` within your end world folder. See the [Configuration Guide](https://docs.papermc.io/paper/reference/configuration) for more information. anticheat: anti-xray: enabled: false FAQ, common pitfalls and support -------------------------------- [Section titled “FAQ, common pitfalls and support”](https://docs.papermc.io/paper/anti-xray/#faq-common-pitfalls-and-support) I can still see (some) ores / use X-ray As described above, there are several reasons why you might still see (some) ores even though you have enabled Anti-Xray: * The ores are above the configured `max-block-height` value. * Anti-Xray cannot hide ores exposed to air or other transparent blocks (in caves for example). In principle this is also the case for `engine-mode: 2` and `engine-mode: 3`, however, usually the fake ores obstruct the view of real blocks. Hiding those exposed ores too requires additional plugins. * The `use-permission` option is enabled and you have the Anti-Xray bypass permission (`paper.antixray.bypass`) or you have operator status. * The block type is missing in the configured block lists. This can be the result of using an outdated configuration file. I have added fake blocks but X-ray doesn’t show them If you use `engine-mode: 2` or `engine-mode: 3` and you have added fake blocks to the `hidden-blocks` list but you can’t see them in-game using X-ray, this can have the following reasons: * The added block types are tile entities. Anti-Xray can hide (replace) tile entities (such as chests), provided that they are not exposed to air or other transparent blocks. However, Anti-Xray can’t place tile entities as fake blocks into the chunk. * The block is disabled in your client’s X-ray mod or not shown by your X-ray resource pack. It doesn’t work below y = 0 or in certain other places. * Your configuration file is probably outdated and missing important blocks in the `replacement-blocks` list, such as `deepslate` or biome-specific blocks, such as `basalt`. You might also want to check if the `hidden-blocks` list includes all important ores and their `deepslate` variants. * If it doesn’t work above a certain y-level, check your `max-block-height` setting. It still doesn’t work, further troubleshooting * Make sure to always restart your server after making changes to the Anti-Xray configuration. Changes won’t be applied automatically. * Do not use the `/reload` command. To apply Anti-Xray configuration changes a restart is required. * After restarting the server, verify that the configuration is applied correctly by inspecting the config sections with timings or spark. How and where do I ask for support if it still doesn’t work? If the above bullet points don’t solve your problem or if you have further questions about Anti-Xray, please don’t hesitate to ask us on the [PaperMC Discord](https://discord.gg/papermc) using the #paper-help channel. Please try to provide as much detail as possible about your problem. “It doesn’t work” isn’t very helpful when asking for support. Describe what you want to achieve, what you have tried, what you expect and what you observe. Ideally include a timings or spark link and a picture what you observe in-game. Footnotes --------- [Section titled “Footnotes”](https://docs.papermc.io/paper/anti-xray/#footnote-label) 1. Image design by `Oberfail`, initially posted in the [PaperMC Discord](https://discord.gg/papermc) . [↩](https://docs.papermc.io/paper/anti-xray/#user-content-fnref-1) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Location | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/arguments/location/#_top) Location ======== Block position argument ----------------------- [Section titled “Block position argument”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#block-position-argument) The block position argument is used for retrieving the position of a block. It works the same way as the first argument of the `/setblock ` Vanilla command. In order to retrieve the `BlockPosition` variable from the [`BlockPositionResolver`](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/BlockPositionResolver.html) , we have to resolve it using the command source. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#example-usage) public static LiteralCommandNode blockPositionArgument() { return Commands.literal("blockpositionargument") .then(Commands.argument("arg", ArgumentTypes.blockPosition()) .executes(ctx -> { final BlockPositionResolver blockPositionResolver = ctx.getArgument("arg", BlockPositionResolver.class); final BlockPosition blockPosition = blockPositionResolver.resolve(ctx.getSource()); ctx.getSource().getSender().sendPlainMessage("Put in " + blockPosition.x() + " " + blockPosition.y() + " " + blockPosition.z()); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#in-game-preview) Your device does not support video playback. Fine position argument ---------------------- [Section titled “Fine position argument”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#fine-position-argument) The fine position argument works similarly to the block position argument, with the only difference being that it can accept decimal (precise) location input. The optional overload (`ArgumentTypes.finePosition(boolean centerIntegers)`), which defaults to false if not set, will center whole input, meaning 5 becomes 5.5 (5.0 would stay as 5.0 though), as that is the “middle” of a block. This only applies to X/Z. The y coordinate is untouched by this operation. This argument returns a [`FinePositionResolver`](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/FinePositionResolver.html) . You can resolve that by running `FinePositionResolver#resolve(CommandSourceStack)` to get the resulting [`FinePosition`](https://jd.papermc.io/paper/io/papermc/paper/math/FinePosition.html) . ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#example-usage-1) public static LiteralCommandNode finePositionArgument() { return Commands.literal("fineposition") .then(Commands.argument("arg", ArgumentTypes.finePosition(true)) .executes(ctx -> { final FinePositionResolver resolver = ctx.getArgument("arg", FinePositionResolver.class); final FinePosition finePosition = resolver.resolve(ctx.getSource()); ctx.getSource().getSender().sendRichMessage("Position: ", Placeholder.unparsed("x", Double.toString(finePosition.x())), Placeholder.unparsed("y", Double.toString(finePosition.y())), Placeholder.unparsed("z", Double.toString(finePosition.z())) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#in-game-preview-1) Your device does not support video playback. World argument -------------- [Section titled “World argument”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#world-argument) This argument allows the user to select one of the currently loaded world. You can retrieve the result of that as a generic Bukkit [`World`](https://jd.papermc.io/paper/org/bukkit/World.html) object. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#example-usage-2) public static LiteralCommandNode worldArgument() { return Commands.literal("teleport-to-world") .then(Commands.argument("world", ArgumentTypes.world()) .executes(ctx -> { final World world = ctx.getArgument("world", World.class); if (ctx.getSource().getExecutor() instanceof Player player) { player.teleport(world.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.COMMAND); ctx.getSource().getSender().sendRichMessage("Successfully teleported to ", Placeholder.component("player", player.name()), Placeholder.unparsed("world", world.getName()) ); return Command.SINGLE_SUCCESS; } ctx.getSource().getSender().sendRichMessage("This command requires a player!"); return Command.SINGLE_SUCCESS; }) ).build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/location/#in-game-preview-2) Your device does not support video playback. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Enums | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#_top) Enums ===== Entity anchor argument ---------------------- [Section titled “Entity anchor argument”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#entity-anchor-argument) The entity anchor argument has two valid inputs: `feet` and `eyes`. The resulting [`LookAnchor`](https://jd.papermc.io/paper/io/papermc/paper/entity/LookAnchor.html) is mainly used for methods like [`Entity#lookAt(Position, LookAnchor)`](https://jd.papermc.io/paper/org/bukkit/entity/Entity.html#lookAt(io.papermc.paper.math.Position,io.papermc.paper.entity.LookAnchor)) or [`Player#lookAt(Entity, LookAnchor, LookAnchor)`](https://jd.papermc.io/paper/org/bukkit/entity/Player.html#lookAt(org.bukkit.entity.Entity,io.papermc.paper.entity.LookAnchor,io.papermc.paper.entity.LookAnchor)) . ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#example-usage) public static LiteralCommandNode entityAnchorArgument() { return Commands.literal("entityanchor") .then(Commands.argument("arg", ArgumentTypes.entityAnchor()) .executes(ctx -> { final LookAnchor lookAnchor = ctx.getArgument("arg", LookAnchor.class); ctx.getSource().getSender().sendRichMessage("You chose !", Placeholder.unparsed("anchor", lookAnchor.name()) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#in-game-preview) Your device does not support video playback. GameMode argument ----------------- [Section titled “GameMode argument”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#gamemode-argument) The game mode argument works the same way as the first argument of the Vanilla `/gamemode ` command. It accepts any of the 4 valid game modes, returning a [`GameMode`](https://jd.papermc.io/paper/org/bukkit/GameMode.html) enum to use in code. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#example-usage-1) public static LiteralCommandNode gameModeArgument() { return Commands.literal("gamemodearg") .then(Commands.argument("arg", ArgumentTypes.gameMode()) .executes(ctx -> { final GameMode gamemode = ctx.getArgument("arg", GameMode.class); if (ctx.getSource().getExecutor() instanceof Player player) { player.setGameMode(gamemode); player.sendRichMessage("Your gamemode has been set to !", Placeholder.component("gamemode", Component.translatable(gamemode)) ); return Command.SINGLE_SUCCESS; } ctx.getSource().getSender().sendPlainMessage("This command requires a player!"); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#in-game-preview-1) Your device does not support video playback. HeightMap argument ------------------ [Section titled “HeightMap argument”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#heightmap-argument) The [`HeightMap`](https://jd.papermc.io/paper/org/bukkit/HeightMap.html) argument consists of the following, valid inputs: `motion_blocking`, `motion_blocking_no_leaves`, `ocean_floor`, and `world_surface`. It is often used for declaring relative positioning for data packs or the `/execute positioned over ` command. E.g. `world_surface` would mean that the Y coordinate of the surface of the world on the set X/Z values should be used. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#example-usage-2) public static LiteralCommandNode heightMapArgument() { return Commands.literal("heightmap") .then(Commands.argument("arg", ArgumentTypes.heightMap()) .executes(ctx -> { final HeightMap heightMap = ctx.getArgument("arg", HeightMap.class); ctx.getSource().getSender().sendRichMessage("You selected ", Placeholder.unparsed("selection", heightMap.name()) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#in-game-preview-2) Your device does not support video playback. Scoreboard display slot argument -------------------------------- [Section titled “Scoreboard display slot argument”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#scoreboard-display-slot-argument) This argument allows you to retrieve a [`DisplaySlot`](https://jd.papermc.io/paper/org/bukkit/scoreboard/DisplaySlot.html) enum value from the user. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#example-usage-3) public static LiteralCommandNode scoreboardDisplaySlotArgument() { return Commands.literal("scoreboarddisplayslot") .then(Commands.argument("slot", ArgumentTypes.scoreboardDisplaySlot()) .executes(ctx -> { final DisplaySlot slot = ctx.getArgument("slot", DisplaySlot.class); ctx.getSource().getSender().sendPlainMessage("You selected: " + slot.getId()); return Command.SINGLE_SUCCESS; }) ).build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#in-game-preview-3) Your device does not support video playback. Template mirror argument ------------------------ [Section titled “Template mirror argument”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#template-mirror-argument) Here, the user has 3 valid input possibilities: `front_back`, `left_right`, and `none`. You can retrieve the result of the argument as a [`Mirror`](https://jd.papermc.io/paper/org/bukkit/block/structure/Mirror.html) enum value. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#example-usage-4) public static LiteralCommandNode templateMirrorArgument() { return Commands.literal("templatemirror") .then(Commands.argument("mirror", ArgumentTypes.templateMirror()) .executes(ctx -> { final Mirror mirror = ctx.getArgument("mirror", Mirror.class); ctx.getSource().getSender().sendPlainMessage("You selected: " + mirror.name()); return Command.SINGLE_SUCCESS; }) ).build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#in-game-preview-4) Your device does not support video playback. Template rotation argument -------------------------- [Section titled “Template rotation argument”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#template-rotation-argument) For the template rotation argument, the user has 4 valid input possibilities: `180`, `clockwise_90`, `counterclockwise_90`, and `none`. You can retrieve the result of the argument as a [`StructureRotation`](https://jd.papermc.io/paper/org/bukkit/block/structure/StructureRotation.html) enum value. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#example-usage-5) public static LiteralCommandNode templateRotationArgument() { return Commands.literal("templaterotation") .then(Commands.argument("rotation", ArgumentTypes.templateRotation()) .executes(ctx -> { final StructureRotation rotation = ctx.getArgument("rotation", StructureRotation.class); ctx.getSource().getSender().sendPlainMessage("You selected: " + rotation.name()); return Command.SINGLE_SUCCESS; }) ).build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/enums/#in-game-preview-5) Your device does not support video playback. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Internationalization | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/component-api/i18n/#_top) Internationalization ==================== Generally it’s a good idea to support translations in your plugin, especially if you want to appeal to the largest user base. Adventure makes this simple by adding a server-side translation layer to almost all text that ends up being displayed to clients. GlobalTranslator ---------------- [Section titled “GlobalTranslator”](https://docs.papermc.io/paper/dev/component-api/i18n/#globaltranslator) All translation is done through [`GlobalTranslator`](https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/GlobalTranslator.html) . You can render translations yourself and add new sources for translations. You can add sources to the `GlobalTranslator` by creating instances of [`TranslationStore`](https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/TranslationStore.html) or implementing the [`Translator`](https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/Translator.html) interface yourself. Where translations work ----------------------- [Section titled “Where translations work”](https://docs.papermc.io/paper/dev/component-api/i18n/#where-translations-work) Vanilla Minecraft handles translations on the client by using the language files bundled with the client or provided via resource packs. If you don’t want to send custom language files in a resource pack, server-side translations are the only alternative. They work anywhere the component API exists, except for [`ItemStack`](https://jd.papermc.io/paper/org/bukkit/inventory/ItemStack.html) display text like the display name or lore. So chat, entity display names, scoreboards, tab lists, etc., all support translations. Examples -------- [Section titled “Examples”](https://docs.papermc.io/paper/dev/component-api/i18n/#examples) ### `ResourceBundle` [Section titled “ResourceBundle”](https://docs.papermc.io/paper/dev/component-api/i18n/#resourcebundle) some.translation.key=Translated Message: {0} TranslationStore.StringBased store = TranslationStore.messageFormat(Key.key("namespace:value")); ResourceBundle bundle = ResourceBundle.getBundle("your.plugin.Bundle", Locale.US);store.registerAll(Locale.US, bundle, true);GlobalTranslator.translator().addSource(store); This creates a new `TranslationStore` under a specified namespace. Then, a [`ResourceBundle`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/ResourceBundle.html) is created from a bundle located on the classpath with the specified [`Locale`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Locale.html) . Finally, that `ResourceBundle` is added to the store. That store is then added as a source to the `GlobalTranslator`. This makes all the translations available server-side. Now you can use your translation keys in translatable components. Component.translatable("some.translation.key", Component.text("The Argument")) This will show to clients using the US English language: `Translated Message: The Argument`. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Audiences | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/component-api/audiences/#_top) Audiences ========= Audiences wrap a collection of recipients that can receive messages. They can be used to send messages to individual players, groups of players, or even the entire server (including the console). Who is an `Audience`? --------------------- [Section titled “Who is an Audience?”](https://docs.papermc.io/paper/dev/component-api/audiences/#who-is-an-audience) All `CommandSender`s are single audiences. This includes players, the console, and command blocks. `Server`, `Team` and `World` are all forwarding audiences. This means that they are made up of multiple audiences. For example, the server is made up of all online players and the console. This means that all the [`Audience`](https://jd.advntr.dev/api/latest/net/kyori/adventure/audience/Audience.html) methods are available on [`CommandSender`](https://jd.papermc.io/paper/org/bukkit/command/CommandSender.html) , [`Server`](https://jd.papermc.io/paper/org/bukkit/Server.html) , [`Team`](https://jd.papermc.io/paper/org/bukkit/scoreboard/Team.html) and [`World`](https://jd.papermc.io/paper/org/bukkit/World.html) . `ForwardingAudience` -------------------- [Section titled “ForwardingAudience”](https://docs.papermc.io/paper/dev/component-api/audiences/#forwardingaudience) The [`ForwardingAudience`](https://jd.advntr.dev/api/latest/net/kyori/adventure/audience/ForwardingAudience.html) wraps a collection of [`Audience`](https://jd.advntr.dev/api/latest/net/kyori/adventure/audience/Audience.html) instances and forwards messages to all of them. This is useful for sending messages to multiple audiences (players) at once. // Server is a ForwardingAudience which includes all online players and the consoleForwardingAudience audience = Bukkit.getServer(); // To construct an audience from a collection of players, use:Audience audience = Audience.audience(Audience...);// If you pass in a single Audience, it will be returned as-is. If you pass in a collection of Audiences, they will be// wrapped in a ForwardingAudience. What do `Audience`s do? ----------------------- [Section titled “What do Audiences do?”](https://docs.papermc.io/paper/dev/component-api/audiences/#what-do-audiences-do) Audiences are used for interacting with players. They can be used to send messages, play sounds, show bossbars, and more. They are mostly used for sending other parts of the API to players. For example, you can send a [`Component`](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/Component.html) to a player using [`Audience#sendMessage(Component)`](https://jd.advntr.dev/api/latest/net/kyori/adventure/audience/Audience.html#sendMessage(net.kyori.adventure.text.Component)) . Pointers -------- [Section titled “Pointers”](https://docs.papermc.io/paper/dev/component-api/audiences/#pointers) Audiences can also provide arbitrary information, such as display name or UUID. This is done using the pointer system. // Get the uuid from an audience member, returning an OptionalOptional uuid = audience.get(Identity.UUID); // Get the display name, returning a defaultComponent name = audience.getOrDefault(Identity.DISPLAY_NAME, Component.text("no display name!")); Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Predicates | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#_top) Predicates ========== A predicate allows for checking for valid values. These arguments are dedicated to checking whether some sort of value is valid according to user input. Double range argument --------------------- [Section titled “Double range argument”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#double-range-argument) This argument can be used as a predicate for numbers, which require precise input. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#example-usage) public static LiteralCommandNode doubleRangeArgument() { return Commands.literal("doublerange") .then(Commands.argument("arg", ArgumentTypes.doubleRange()) .executes(ctx -> { final DoubleRangeProvider doubleRangeProvider = ctx.getArgument("arg", DoubleRangeProvider.class); final CommandSender sender = ctx.getSource().getSender(); for (int i = 0; i < 5; i++) { sender.sendRichMessage("Is in bounds? ", Placeholder.unparsed("index", Integer.toString(i)), Placeholder.unparsed("result", Boolean.toString(doubleRangeProvider.range().test((double) i))) ); } return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#in-game-preview) Your device does not support video playback. Integer range argument ---------------------- [Section titled “Integer range argument”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#integer-range-argument) This argument works very similarly to the double range argument, with the only difference being that this argument only accepts integers. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#example-usage-1) public static LiteralCommandNode integerRangeArgument() { return Commands.literal("integerrange") .then(Commands.argument("range", ArgumentTypes.integerRange()) .then(Commands.argument("tested_integer", IntegerArgumentType.integer()) .executes(MinecraftArguments::runIntegerRangeCommand))) .build();} private static int runIntegerRangeCommand(final CommandContext ctx) { final IntegerRangeProvider integerRangeProvider = ctx.getArgument("range", IntegerRangeProvider.class); final int integerToTest = IntegerArgumentType.getInteger(ctx, "tested_integer"); if (integerRangeProvider.range().contains(integerToTest)) { ctx.getSource().getSender().sendRichMessage(" is inside the specified range!", Placeholder.unparsed("input", Integer.toString(integerToTest)) ); return Command.SINGLE_SUCCESS; } ctx.getSource().getSender().sendRichMessage(" is not inside the specified range!", Placeholder.unparsed("input", Integer.toString(integerToTest)) ); return Command.SINGLE_SUCCESS;} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#in-game-preview-1) Your device does not support video playback. Item predicate argument ----------------------- [Section titled “Item predicate argument”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#item-predicate-argument) This argument allows for checking whether an item fits some predicate. It is useful for filtering out certain items based on some criteria. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#example-usage-2) public static LiteralCommandNode itemPredicateArgument() { return Commands.literal("itempredicate") .then(Commands.argument("predicate", ArgumentTypes.itemPredicate()) .executes(ctx -> { final ItemStackPredicate predicate = ctx.getArgument("predicate", ItemStackPredicate.class); final ItemStack defaultWoodenSword = ItemType.WOODEN_SWORD.createItemStack(); ctx.getSource().getSender().sendRichMessage("Does predicate include a default wooden sword? ", Placeholder.parsed("result", predicate.test(defaultWoodenSword) ? "true" : "false") ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/predicate/#in-game-preview-2) Your device does not support video playback. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Frequently asked questions | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/faq/#_top) Frequently asked questions ========================== Unsupported Java detected, what do I do?! ----------------------------------------- [Section titled “Unsupported Java detected, what do I do?!”](https://docs.papermc.io/paper/faq/#unsupported-java-detected-what-do-i-do) Unsupported, early-access, or internal versions of Java are often missing features, have known issues or be straight up broken. As such, we cannot provide support for servers running such versions. You should install a supported version of Java as explained [here](https://docs.papermc.io/misc/java-install) . If you still wish to continue, knowing that you are on your own and will receive NO support, you can disable the check with a system property, as explained [here](https://docs.papermc.io/paper/reference/system-properties#paperignorejavaversion) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Requirements | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/basics/requirements/#_top) Requirements ============ Sometimes you want to limit a player’s ability to use and/or view certain commands or subcommands. Exactly for this purpose, the `ArgumentBuilder` class has a `requires(Predicate)` method to define a requirement in order to use that specific branch of a command tree. As always, the generic parameter `S` is just a `CommandSourceStack`, providing us with the executing entity, the command sender, and the location of the command. Defining permissions -------------------- [Section titled “Defining permissions”](https://docs.papermc.io/paper/dev/command-api/basics/requirements/#defining-permissions) One of the most common usecases for requirements are permissions. Usually, these are checked on the **command sender**, as that is the actual entity/console/object which ran the command, even if it is run as someone else (the executor). A simple command with a permission might look like this: Commands.literal("testcmd") .requires(sender -> sender.getSender().hasPermission("permission.test")) .executes(ctx -> { ctx.getSource().getSender().sendRichMessage("You have permission to run this command!"); return Command.SINGLE_SUCCESS; }); This command requires the `permission.test` permission to be had by a sender. But you cannot only define permissions, you can also require a sender to be a server operator, like this: Commands.literal("testcmd") .requires(sender -> sender.getSender().isOp()) .executes(ctx -> { ctx.getSource().getSender().sendRichMessage("You are a server operator!"); return Command.SINGLE_SUCCESS; }); Defining more advanced predicates --------------------------------- [Section titled “Defining more advanced predicates”](https://docs.papermc.io/paper/dev/command-api/basics/requirements/#defining-more-advanced-predicates) You don’t have to limit yourself to checking just for permissions - since it is a predicate, any boolean can be returned. For example, you can check for whether a player has a diamond sword in their inventory: Commands.literal("givesword") .requires(sender -> sender.getExecutor() instanceof Player player && !player.getInventory().contains(Material.DIAMOND_SWORD)) .executes(ctx -> { if (ctx.getSource().getExecutor() instanceof Player player) { player.getInventory().addItem(ItemType.DIAMOND_SWORD.createItemStack()); } return Command.SINGLE_SUCCESS; }); At first glance, this works just fine. But it does have a very big flaw - since the player’s client is not aware of the requirement, it still shows the command as executable, even if the requirement resolves as false. But if the client tries to run the command, the server reports that this command doesn’t exist (meaning the requirement was not met): ![](https://docs.papermc.io/_astro/client-server-mismatch.CZCt4lWh_ZJuoEL.webp) How can we solve this? The `Player` interface has a method called [`#updateCommands()`](https://jd.papermc.io/paper/org/bukkit/entity/Player.html#updateCommands()) just for this usecase. It resends the currently registered commands back to the client in an attempt to reload commands. For now, we can create a new command with which the player can update its own commands in order to resync its command state: Commands.literal("reloadcommands") .executes(ctx -> { if (ctx.getSource().getExecutor() instanceof Player player) { player.updateCommands(); player.sendRichMessage("Successfully updated your commands!"); } return Command.SINGLE_SUCCESS; }); ### Automating command reloads [Section titled “Automating command reloads”](https://docs.papermc.io/paper/dev/command-api/basics/requirements/#automating-command-reloads) Forcing a player to reload their own commands is not a viable option for user experience. For this reason, you can **automate** this behavior. It is safe to call the update commands method as often as required, but it should generally be avoided as it can cost a great deal of bandwidth. If possible, you should instead place these in very specific spots. Furthermore, this method is completely thread safe, meaning you are free to call it from an asynchronous context. Restricted commands ------------------- [Section titled “Restricted commands”](https://docs.papermc.io/paper/dev/command-api/basics/requirements/#restricted-commands) From 1.21.6 onwards, commands can now be restricted. This feature is used by Vanilla in order to make a player confirm whether they really want to run a command from a run-command click event. That includes ones on text components or dialog buttons. All Vanilla commands, which require operator status by default, are restricted: ![](https://docs.papermc.io/_astro/vanilla-restriction.DCEks_9m_Z11T8PA.webp) ### Restricting your commands [Section titled “Restricting your commands”](https://docs.papermc.io/paper/dev/command-api/basics/requirements/#restricting-your-commands) You can apply the same behavior to your commands by wrapping the predicate inside your `.requires` with `Commands.restricted(...)`. A simple implementation might look like this: Commands.literal("test-req") .requires(Commands.restricted(source -> true)) .executes(ctx -> { ctx.getSource().getSender().sendRichMessage("You passed!"); return Command.SINGLE_SUCCESS; }); ![](https://docs.papermc.io/_astro/custom-restriction.BpXtkwe6_Z1qbUAM.webp) Inside the `.restricted` method you can put any logic which you would put into your `.requires` method. It is nothing more but a simple wrapper around the usual `.requires` predicate: Commands.literal("mycommand") .requires(Commands.restricted(source -> source.getSender().hasPermission("my.custom.permission") && source.getExecutor() instanceof Player player && player.getGameMode() == GameMode.ADVENTURE)) .executes(ctx -> { // Command logic }); Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # commands.yml | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/reference/bukkit-commands-configuration/#_top) commands.yml ============ command-block-overrides: [#](https://docs.papermc.io/paper/reference/bukkit-commands-configuration/#command_block_overrides) \- Which Vanilla commands should be prioritized over those provided by Bukkit or plugins. Useful for compatibility with adventure maps built for Vanilla command blocks. Use the literal ”\*” to always use the Vanilla version in command blocks. By default, no commands are overridden. ignore-vanilla-permissions: false[#](https://docs.papermc.io/paper/reference/bukkit-commands-configuration/#ignore_vanilla_permissions) Whether to use Vanilla permission levels when executing commands. aliases: [#](https://docs.papermc.io/paper/reference/bukkit-commands-configuration/#aliases) icanhasbukkit: [#](https://docs.papermc.io/paper/reference/bukkit-commands-configuration/#aliases_icanhasbukkit) \- version $1- A built-in alias. Set aliases to an empty list (\[\]) to persistently remove. : [#](https://docs.papermc.io/paper/reference/bukkit-commands-configuration/#aliases__alias_name_) \- A list of strings which are target commands. Alternatively, a string, which is a single target command. A target command is a command that is run, when the alias is run. Replacements: * `$sender` is replaced with the command sender”s name (Added by Paper). * `$` is replaced by the n”th argument, 1-indexed. * `$$` is replaced by the n”th argument, 1-indexed, failing if the n”th argument is not present. * `$-` is replaced by the n”th argument and everything that follows, 1-indexed. * `$$-` is replaced by the n”th argument and everything that follows, 1-indexed, failing if the n”th argument is not present. Each alias registered cannot (easily) be overridden by a plugin. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Custom events | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/custom-events/#_top) Custom events ============= Creating custom events is a great way to add functionality to your plugin. This will allow other plugins to listen to your custom events and add functionality to your plugin. Creating a custom event ----------------------- [Section titled “Creating a custom event”](https://docs.papermc.io/paper/dev/custom-events/#creating-a-custom-event) To create a custom event, you need to create a class that extends [`Event`](https://jd.papermc.io/paper/org/bukkit/event/Event.html) . Each event requires a [`HandlerList`](https://jd.papermc.io/paper/org/bukkit/event/HandlerList.html) that will contain all the listeners that are listening to that event. The only exception to this requirement is when you have an event class that cannot be fired, but serves as a parent for other events instead. An example of this is [`BlockPistonEvent`](https://jd.papermc.io/paper/org/bukkit/event/block/BlockPistonEvent.html) , which cannot be listened to directly. This list is used to call the listeners when the event is called. public class PaperIsCoolEvent extends Event { private static final HandlerList HANDLER_LIST = new HandlerList(); public static HandlerList getHandlerList() { return HANDLER_LIST; } @Override public HandlerList getHandlers() { return HANDLER_LIST; }} Now that we have created our event, we can add some functionality to it. Perhaps this will contain a message that will be broadcast to the server when the event is called. public class PaperIsCoolEvent extends Event { private static final HandlerList HANDLER_LIST = new HandlerList(); private Component message; public PaperIsCoolEvent(Component message) { this.message = message; } public Component getMessage() { return this.message; } public void setMessage(Component message) { this.message = message; } public static HandlerList getHandlerList() { return HANDLER_LIST; } @Override public HandlerList getHandlers() { return HANDLER_LIST; }} Calling the event ----------------- [Section titled “Calling the event”](https://docs.papermc.io/paper/dev/custom-events/#calling-the-event) Now that we have created our event, we can call it. public class ExamplePlugin extends JavaPlugin { // ... public void callCoolPaperEvent() { PaperIsCoolEvent coolEvent = new PaperIsCoolEvent(Component.text("Paper is cool!")); coolEvent.callEvent(); // Plugins could have changed the message from inside their listeners here. So we need to get the message again. // This event structure allows for other plugins to change the message to their taste. // Like, for example, a plugin that adds a prefix to all messages. Bukkit.broadcast(coolEvent.getMessage()); }} Implementing cancellation ------------------------- [Section titled “Implementing cancellation”](https://docs.papermc.io/paper/dev/custom-events/#implementing-cancellation) If you want to allow your event to be cancelled, you can implement the `Cancellable` interface. public class PaperIsCoolEvent extends Event implements Cancellable { private static final HandlerList HANDLER_LIST = new HandlerList(); private Component message; private boolean cancelled; // ... @Override public boolean isCancelled() { return this.cancelled; } @Override public void setCancelled(boolean cancelled) { this.cancelled = cancelled; }} Now, when the event is called, you can check if it is cancelled and act accordingly. public class ExamplePlugin extends JavaPlugin { // ... public void callCoolPaperEvent() { PaperIsCoolEvent coolEvent = new PaperIsCoolEvent(Component.text("Paper is cool!")); coolEvent.callEvent(); if (!coolEvent.isCancelled()) { Bukkit.broadcast(coolEvent.getMessage()); } }} When an event is cancellable, [`Event#callEvent()`](https://jd.papermc.io/paper/org/bukkit/event/Event.html#callEvent()) will return false if the event was cancelled. This allows you to directly use `callEvent` in your `if` statement, instead of having to check [`Cancellable#isCancelled()`](https://jd.papermc.io/paper/org/bukkit/event/Cancellable.html#isCancelled()) manually. public class ExamplePlugin extends JavaPlugin { // ... public void callCoolPaperEvent() { PaperIsCoolEvent coolEvent = new PaperIsCoolEvent(Component.text("Paper is cool!")); if (coolEvent.callEvent()) { // Directly get the output from callEvent Bukkit.broadcast(coolEvent.getMessage()); } }} Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Entities and players | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#_top) Entities and players ==================== The arguments described in this section relate to arguments which you can use to retrieve entities. Their main usage is the selection of command targets. All of these have entity selectors (`@a`, `@e`, `@n`, etc.) as valid inputs, though they require the `minecraft.command.selector` permission in order to be able to be used. The specific arguments may allow or disallow certain selectors. Due to the permission requirement for selectors it is advised to add a `requires` statement to your command: .requires(ctx -> ctx.getSender().hasPermission("minecraft.command.selector")) You can find more information about requirements [here](https://docs.papermc.io/paper/dev/command-api/basics/requirements) . Entity argument --------------- [Section titled “Entity argument”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#entity-argument) This argument, after resolving its returning `EntitySelectorArgumentResolver`, returns a list of exactly one, no more and no less, entity. It is safe to call `List#getFirst()` to retrieve that entity. You can resolve it using [`ArgumentResolver#resolve(CommandSourceStack)`](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/ArgumentResolver.html#resolve(io.papermc.paper.command.brigadier.CommandSourceStack)) ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#example-usage) public static LiteralCommandNode entityArgument() { return Commands.literal("entityarg") .then(Commands.argument("arg", ArgumentTypes.entity()) .executes(ctx -> { final EntitySelectorArgumentResolver entitySelectorArgumentResolver = ctx.getArgument("arg", EntitySelectorArgumentResolver.class); final List entities = entitySelectorArgumentResolver.resolve(ctx.getSource()); ctx.getSource().getSender().sendRichMessage("Found ", Placeholder.component("entityname", entities.getFirst().name()) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#in-game-preview) If the executing player doesn’t have the `minecraft.command.selector` permission: Your device does not support video playback. If the executing player has the `minecraft.command.selector` permission: Your device does not support video playback. Entities argument ----------------- [Section titled “Entities argument”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#entities-argument) In contrast to the single entity argument, this multiple-entities argument accepts any amount of entities, with the minimum amount of entities being 1. They can, once again, be resolved using [`ArgumentResolver#resolve(CommandSourceStack)`](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/resolvers/ArgumentResolver.html#resolve(io.papermc.paper.command.brigadier.CommandSourceStack)) , which returns a `List`. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#example-usage-1) public static LiteralCommandNode entitiesArgument() { return Commands.literal("entitiesarg") .then(Commands.argument("arg", ArgumentTypes.entities()) .executes(ctx -> { final EntitySelectorArgumentResolver entitySelectorArgumentResolver = ctx.getArgument("arg", EntitySelectorArgumentResolver.class); final List entities = entitySelectorArgumentResolver.resolve(ctx.getSource()); final Component foundEntities = Component.join(JoinConfiguration.commas(true), entities.stream().map(Entity::name).toList()); ctx.getSource().getSender().sendRichMessage("Found ", Placeholder.component("entitynames", foundEntities) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#in-game-preview-1) Your device does not support video playback. Player argument --------------- [Section titled “Player argument”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#player-argument) The player argument allows to retrieve a `PlayerSelectorArgumentResolver` for player arguments. For this “single player” argument, you can safely get the target player by running `PlayerSelectorArgumentResolver.resolve(ctx.getSource()).getFirst()`, which returns a [Player](https://jd.papermc.io/paper/org/bukkit/entity/Player.html) object. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#example-usage-2) This command yeets the targeted player into the air! public static LiteralCommandNode playerArgument() { return Commands.literal("player") .then(Commands.argument("target", ArgumentTypes.player()) .executes(ctx -> { final PlayerSelectorArgumentResolver targetResolver = ctx.getArgument("target", PlayerSelectorArgumentResolver.class); final Player target = targetResolver.resolve(ctx.getSource()).getFirst(); target.setVelocity(new Vector(0, 100, 0)); target.sendRichMessage("Yeeeeeeeeeet"); ctx.getSource().getSender().sendRichMessage("Yeeted !", Placeholder.component("target", target.name()) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#in-game-preview-2) Your device does not support video playback. Players argument ---------------- [Section titled “Players argument”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#players-argument) The “multiple players” argument works similarly to the “single player” argument, also returning a `PlayerSelectorArgumentResolver`. Instead of just resolving to exactly one `Player`, this one can resolve to more than just one player - which you should account for in case of using this argument. `PlayerSelectorArgumentResolver.resolve(ctx.getSource())` returns a `List`, which you can just iterate through. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#example-usage-3) Extending the “single player” yeet command to support multiple targets can look like this: public static LiteralCommandNode playersArgument() { return Commands.literal("players") .then(Commands.argument("targets", ArgumentTypes.players()) .executes(ctx -> { final PlayerSelectorArgumentResolver targetResolver = ctx.getArgument("targets", PlayerSelectorArgumentResolver.class); final List targets = targetResolver.resolve(ctx.getSource()); final CommandSender sender = ctx.getSource().getSender(); for (final Player target : targets) { target.setVelocity(new Vector(0, 100, 0)); target.sendRichMessage("Yeeeeeeeeeet"); sender.sendRichMessage("Yeeted !", Placeholder.component("target", target.name()) ); } return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#in-game-preview-3) Your device does not support video playback. Player profiles argument ------------------------ [Section titled “Player profiles argument”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#player-profiles-argument) The player profiles argument is a very powerful argument which can retrieve both offline and online players. It returns the result of the argument as a `PlayerProfileListResolver`, which resolves to a `Collection`. This collection can be iterated to get the resulting profile(s). Usually, it only returns a single `PlayerProfile` if retrieving a player by name, but it can return multiple if using the entity selectors (like `@a` on online players). Thus it always makes sense to run whatever operation you want to run on all entries in the collection instead of just the first one. This argument will run API calls to Mojang servers in order to retrieve player information for players which have never joined the server before. Due to this operation sometimes taking a bit longer, it is suggested to resolve this argument in an asynchronous context in order to not cause any server lag. Sometimes, these API calls may fail. This is also visible in the in-game preview down below. This behavior is also the reason for `/whitelist add` sometimes. ### Example usage - player lookup command [Section titled “Example usage - player lookup command”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#example-usage---player-lookup-command) public static LiteralCommandNode playerProfilesArgument() { return Commands.literal("lookup") .then(Commands.argument("profile", ArgumentTypes.playerProfiles()) .executes(ctx -> { final PlayerProfileListResolver profilesResolver = ctx.getArgument("profile", PlayerProfileListResolver.class); final Collection foundProfiles = profilesResolver.resolve(ctx.getSource()); for (final PlayerProfile profile : foundProfiles) { ctx.getSource().getSender().sendPlainMessage("Found " + profile.getName()); } return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/entity-player/#in-game-preview-4) Your device does not support video playback. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Entity Pathfinder API | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/entity-pathfinder/#_top) Entity Pathfinder API ===================== The Entity Pathfinder API can be used to control the movement of entities in Minecraft. It allows you to set a path for an entity to follow, such as moving to a location or following a player. Accessing the pathfinder ------------------------ [Section titled “Accessing the pathfinder”](https://docs.papermc.io/paper/dev/entity-pathfinder/#accessing-the-pathfinder) To access the pathfinder for a mob, you need to call [`getPathfinder()`](https://jd.papermc.io/paper/org/bukkit/entity/Mob.html#getPathfinder()) on the mob. This will return an instance of [`Pathfinder`](https://jd.papermc.io/paper/com/destroystokyo/paper/entity/Pathfinder.html) . Let’s say that you have a [`Cow`](https://jd.papermc.io/paper/org/bukkit/entity/Cow.html) and want to move it to a player. You can do this by getting the pathfinder for the cow and then setting the path to the player’s location: Cow cow = ...;Player player = ...; Pathfinder pathfinder = cow.getPathfinder();// moveTo returns a boolean indicating whether the path was set successfullyboolean success = pathfinder.moveTo(player.getLocation()); If you want to access the current path for the cow, you can call [`getPathfinder()`](https://jd.papermc.io/paper/org/bukkit/entity/Mob.html#getPathfinder()) on the pathfinder: PathResult path = pathfinder.getCurrentPath(); // A PathResult is essentially a wrapper around a List of Locations. These can be accessed with:List locations = path.getPoints();// It is important to note that the list contains points that have already been passed,// as well as future points. If you want to get the next point, you can use:Location nextPoint = path.getNextPoint(); // Or locations.get(path.getNextPointIndex())// Finally, you can access the final destination with:Location destination = path.getFinalPoint(); Pathfinding rules ----------------- [Section titled “Pathfinding rules”](https://docs.papermc.io/paper/dev/entity-pathfinder/#pathfinding-rules) The pathfinder is limited by Minecraft’s own pathfinding logic. For example, a polar bear cannot fly. This means that if you set a path for a polar bear to a location that is in the air, it will not be able to reach it. Some attributes can be set on the pathfinder to change the way that the pathfinder works. These are: * [`setCanOpenDoors(boolean)`](https://jd.papermc.io/paper/com/destroystokyo/paper/entity/Pathfinder.html#setCanOpenDoors(boolean)) : Whether the entity can open doors. This is relevant for zombies breaking down doors and villagers opening doors. * [`setCanPassDoors(boolean)`](https://jd.papermc.io/paper/com/destroystokyo/paper/entity/Pathfinder.html#setCanPassDoors(boolean)) : Whether the entity can pass through open doors. * [`setCanFloat(boolean)`](https://jd.papermc.io/paper/com/destroystokyo/paper/entity/Pathfinder.html#setCanFloat(boolean)) : Whether the entity can float in water. These methods have respective getters as well. Stopping the pathfinding ------------------------ [Section titled “Stopping the pathfinding”](https://docs.papermc.io/paper/dev/entity-pathfinder/#stopping-the-pathfinding) You can call [`stopPathfinding()`](https://jd.papermc.io/paper/com/destroystokyo/paper/entity/Pathfinder.html#stopPathfinding()) on the pathfinder to cancel the entity from pathfinding. This will also clear the current path. You can use [`hasPath()`](https://jd.papermc.io/paper/com/destroystokyo/paper/entity/Pathfinder.html#hasPath()) to check if the pathfinder is currently running. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Handler lists | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/handler-lists/#_top) Handler lists ============= Every [`Event`](https://jd.papermc.io/paper/org/bukkit/event/Event.html) that can be listened to has a [`HandlerList`](https://jd.papermc.io/paper/org/bukkit/event/HandlerList.html) containing all the listeners that are listening to that event. This list is used to call the listeners when the event is called. Getting the handler list for an event ------------------------------------- [Section titled “Getting the handler list for an event”](https://docs.papermc.io/paper/dev/handler-lists/#getting-the-handler-list-for-an-event) To get the handler list for an event, you can call `getHandlerList()` on the specific event class. public class ExampleListener implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { HandlerList handlerList = event.getHandlerList(); // ... } // Or: public ExampleListener() { // Access the handler list through the static getter HandlerList handlerList = PlayerJoinEvent.getHandlerList(); // ... }} Unregistering a listener ------------------------ [Section titled “Unregistering a listener”](https://docs.papermc.io/paper/dev/handler-lists/#unregistering-a-listener) To unregister a listener, you can call `unregister()` on the `HandlerList` that the listener is registered to. public class ExampleListener implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { HandlerList handlerList = event.getHandlerList(); handlerList.unregister(this); // ... } // Or: public ExampleListener() { // Access the handler list through the static getter HandlerList handlerList = PlayerJoinEvent.getHandlerList(); handlerList.unregister(this); // Granted this is a pretty stupid example... }} You can unregister based on [`Listener`](https://jd.papermc.io/paper/org/bukkit/event/Listener.html) or [`Plugin`](https://jd.papermc.io/paper/org/bukkit/plugin/Plugin.html) for more convenience. Likewise, you can also unregister all listeners for a specific event by calling [`unregisterAll()`](https://jd.papermc.io/paper/org/bukkit/event/HandlerList.html#unregisterAll()) on the `HandlerList`. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # permissions.yml | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/reference/bukkit-permissions-configuration/#_top) permissions.yml =============== : [#](https://docs.papermc.io/paper/reference/bukkit-permissions-configuration/#_permission_) default: op[#](https://docs.papermc.io/paper/reference/bukkit-permissions-configuration/#_permission__default) Who this permission is granted to by default. “true”: all players. “false”: no players. “op”: only operators (also aliased as “isop”, “operator”, “isoperator”, “admin”, and “isadmin”). “!op”: all players except operators (also aliased as “notop”, “!operator”, “notoperator”, “!admin”, “notadmin”). children: [#](https://docs.papermc.io/paper/reference/bukkit-permissions-configuration/#_permission__children) A list (not shown) or a map (shown below) of child permissions. : true[#](https://docs.papermc.io/paper/reference/bukkit-permissions-configuration/#_permission__children__permission_) A child permission of this permission. The value is either a boolean, where false inverts the whether the permission would be granted to this. or a top level permission entry, except the default is this parent permissions default value, and any child permissions of the newly created permission are bubbled up to the top level. description: ""[#](https://docs.papermc.io/paper/reference/bukkit-permissions-configuration/#_permission__description_) The description of the permission. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # help.yml | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#_top) help.yml ======== general-topics: [#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#general_topics) : [#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#general_topics__topic_name_) A custom help “topic” to show when the user types “`/help `”. shortText: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#general_topics__topic_name__shortText) The first line of the help entry, used as a summary in index pages. This is formatted with legacy ”&” style formatting. fullText: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#general_topics__topic_name__fullText) The remaining lines of this help entry. This is formatted with legacy ”&” style formatting. permission: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#general_topics__topic_name__permission) The permission required to view this help entry. If this is empty/not set, the entry does not require a permission. index-topics: [#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#index_topics) : [#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#index_topics__topic_name_) A composite help topic index. If the topic name is the special value “Default”, it will override the automatically generated index used for /help with no arguments. shortText: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#index_topics__topic_name__shortText) The short text used in other index topics. This is not displayed when showing this topic itself. This is formatted with legacy ”&” style formatting. preamble: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#index_topics__topic_name__preamble) Information to show before the index. This is formatted with legacy ”&” style formatting. permission: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#index_topics__topic_name__permission) A custom permission required to view this help entry. If this is empty/not set, the entry does not require a permission. commands: \[\][#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#index_topics__topic_name__commands) What to show in the index. This is a list of commands, or other help topics. They will be displayed in the order they are listed here in “topic name: short text” format. Each entry is a maximum of 1 minimum-width chat line (55 chars). amended-topics: [#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#amended_topics) : [#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#amended_topics__topic_name_) shortText: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#amended_topics__topic_name__shortText) A replacement for the short text of the topic. If this is empty/not set, the original short text is used. If this contains the literal string ``, it will be replaced with the original short text. This is formatted with legacy ”&” style formatting. fullText: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#amended_topics__topic_name__fullText) A replacement for the full text of the topic. If this is empty/not set, the original full text is used. If this contains the literal string ``, it will be replaced with the original full text. This is formatted with legacy ”&” style formatting. permission: ""[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#amended_topics__topic_name__permission) Overrides the permission required to view this help entry. If this is empty/not set, the original permission is NOT used, instead no permission is required. ignore-plugins: \[\][#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#ignore_plugins) A list of plugins to ignore when generating help topics for registered commands. If “All” is included, all plugins are ignored. If the special plugin name “Bukkit” is included, all commands registered by Bukkit are ignored. command-topics-in-master-index: true[#](https://docs.papermc.io/paper/reference/bukkit-help-configuration/#command_topics_in_master_index) Whether to allow command topics (topics starting with a `/`) to be shown in the main index. This is the index shown when the user types “`/help`” or “`/help `”. Command alias topics are always hidden. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Chat events | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/chat-events/#_top) Chat events =========== The chat event has evolved a few times over the years. This guide will explain how to properly use the new [`AsyncChatEvent`](https://jd.papermc.io/paper/io/papermc/paper/event/player/AsyncChatEvent.html) and its [`ChatRenderer`](https://jd.papermc.io/paper/io/papermc/paper/chat/ChatRenderer.html) . The [`AsyncChatEvent`](https://jd.papermc.io/paper/io/papermc/paper/event/player/AsyncChatEvent.html) is an improved version of the old [`AsyncPlayerChatEvent`](https://jd.papermc.io/paper/org/bukkit/event/player/AsyncPlayerChatEvent.html) that allows you to render chat messages individually for each player. Understanding the renderer -------------------------- [Section titled “Understanding the renderer”](https://docs.papermc.io/paper/dev/chat-events/#understanding-the-renderer) Before we can start using the new chat event, we need to understand how the new renderer works. The renderer is Paper’s way of allowing plugins to modify the chat message before it is sent to the player. This is done by using the [`ChatRenderer`](https://jd.papermc.io/paper/io/papermc/paper/chat/ChatRenderer.html) interface with its [`ChatRenderer#render(Player, Component, Component, Audience)`](https://jd.papermc.io/paper/io/papermc/paper/chat/ChatRenderer.html#render(org.bukkit.entity.Player,net.kyori.adventure.text.Component,net.kyori.adventure.text.Component,net.kyori.adventure.audience.Audience)) method. Previously, this was done by using the [`AsyncPlayerChatEvent`](https://jd.papermc.io/paper/org/bukkit/event/player/AsyncPlayerChatEvent.html) with its [`AsyncPlayerChatEvent#setFormat(String)`](https://jd.papermc.io/paper/org/bukkit/event/player/AsyncPlayerChatEvent.html#setFormat(java.lang.String)) method. public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) { // ...} * The [`render`](https://jd.papermc.io/paper/io/papermc/paper/chat/ChatRenderer.html#render(org.bukkit.entity.Player,net.kyori.adventure.text.Component,net.kyori.adventure.text.Component,net.kyori.adventure.audience.Audience)) method is called when a chat message is sent to the player. * The `source` parameter is the player that sent the message. * The `sourceDisplayName` parameter is the display name of the player that sent the message. * The `message` parameter is the message that was sent. * The `viewer` parameter is the player that is receiving the message. Using the renderer ------------------ [Section titled “Using the renderer”](https://docs.papermc.io/paper/dev/chat-events/#using-the-renderer) There are two ways to use the renderer. 1. Implementing the [`ChatRenderer`](https://jd.papermc.io/paper/io/papermc/paper/chat/ChatRenderer.html) interface in a class. 2. Using a lambda expression. Depending on the complexity of your renderer, you may want to use one or the other. ### Implementing the `ChatRenderer` interface [Section titled “Implementing the ChatRenderer interface”](https://docs.papermc.io/paper/dev/chat-events/#implementing-the-chatrenderer-interface) The first way of using the renderer is by implementing the [`ChatRenderer`](https://jd.papermc.io/paper/io/papermc/paper/chat/ChatRenderer.html) interface in a class. In this example, we will be using our `ChatListener` class. Next, we need to tell the event to use the renderer by using the [`AbstractChatEvent#renderer()`](https://jd.papermc.io/paper/io/papermc/paper/event/player/AbstractChatEvent.html#renderer()) method. public class ChatListener implements Listener, ChatRenderer { // Implement the ChatRenderer and Listener interface // Listen for the AsyncChatEvent @EventHandler public void onChat(AsyncChatEvent event) { event.renderer(this); // Tell the event to use our renderer } // Override the render method @Override public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) { // ... }} ### Using a lambda expression [Section titled “Using a lambda expression”](https://docs.papermc.io/paper/dev/chat-events/#using-a-lambda-expression) Another way of using the renderer is by using a lambda expression. public class ChatListener implements Listener { @EventHandler public void onChat(AsyncChatEvent event) { event.renderer((source, sourceDisplayName, message, viewer) -> { // ... }); }} Rendering the message --------------------- [Section titled “Rendering the message”](https://docs.papermc.io/paper/dev/chat-events/#rendering-the-message) Now that we have our renderer, we can start rendering the message. Let’s say we want to render our chat to look like this: ![](https://docs.papermc.io/_astro/plain-message-rendering.CSp3azaV_X1OsX.webp) To do this, we need to return a new [`Component`](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/Component.html) that contains the message we want to send. public class ChatListener implements Listener, ChatRenderer { // Listener logic @Override public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) { return sourceDisplayName .append(Component.text(": ")) .append(message); }} Now you can see that the message is rendered as we wanted it to be. Conclusion ---------- [Section titled “Conclusion”](https://docs.papermc.io/paper/dev/chat-events/#conclusion) That is all you need to know about the new chat event and its renderer. Of course there are many more things you can do with components in general. If you want to learn more about components, you can read the [Component Documentation](https://docs.papermc.io/adventure/text/) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Adventure | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#_top) Adventure ========= These arguments return a class from the `net.kyori` package. They are technically not native to Minecraft or Bukkit, but as Paper includes the Adventure library, they are widely used in the Paper ecosystem. Component argument ------------------ [Section titled “Component argument”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#component-argument) The result is returned as an Adventure component to work with. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#example-usage) public static LiteralCommandNode componentArgument() { return Commands.literal("componentargument") .then(Commands.argument("arg", ArgumentTypes.component()) .executes(ctx -> { final Component component = ctx.getArgument("arg", Component.class); ctx.getSource().getSender().sendRichMessage( "Your message: ", Placeholder.component("input", component) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#in-game-preview) Your device does not support video playback. Key argument ------------ [Section titled “Key argument”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#key-argument) The key argument allows a user to put in any artificial (namespaced) key, ensuring its validity. This returns a [`Key`](https://jd.advntr.dev/key/latest/net/kyori/adventure/key/Key.html) , which can be used at various other places in the Paper API. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#example-usage-1) public static LiteralCommandNode keyArgument() { return Commands.literal("key") .then(Commands.argument("key_input", ArgumentTypes.key()) .executes(ctx -> { final Key key = ctx.getArgument("key_input", Key.class); ctx.getSource().getSender().sendRichMessage("You put in !", Placeholder.unparsed("key", key.asString()) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#in-game-preview-1) Your device does not support video playback. Named color argument -------------------- [Section titled “Named color argument”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#named-color-argument) This argument provides the user with the ability to select between the 16 built-in “named” text colors. This argument returns a [`NamedTextColor`](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/format/NamedTextColor.html) , which you can use for applying a color to components. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#example-usage-2) public static LiteralCommandNode namedColorArgument() { return Commands.literal("namedcolor") .then(Commands.argument("color", ArgumentTypes.namedColor()) .then(Commands.argument("message", StringArgumentType.greedyString()) .executes(ctx -> { final NamedTextColor color = ctx.getArgument("color", NamedTextColor.class); final String msg = StringArgumentType.getString(ctx, "message"); ctx.getSource().getSender().sendMessage( Component.text(msg).color(color) ); return Command.SINGLE_SUCCESS; }))) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#in-game-preview-2) Your device does not support video playback. Adventure style argument ------------------------ [Section titled “Adventure style argument”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#adventure-style-argument) The style argument returns its value in the form of a [`Style`](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/format/Style.html) object. This can be applied to any component using `Component#style(Style)`. Whilst the JSON input allows for the `text` field, its content is completely ignored. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#example-usage-3) public static LiteralCommandNode styleArgument() { return Commands.literal("style") .then(Commands.argument("style", ArgumentTypes.style()) .then(Commands.argument("message", StringArgumentType.greedyString()) .executes(ctx -> { final Style style = ctx.getArgument("style", Style.class); final String msg = StringArgumentType.getString(ctx, "message"); ctx.getSource().getSender().sendRichMessage("Your input: ", Placeholder.component("input", Component.text(message).style(style)) ); return Command.SINGLE_SUCCESS; }))) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#in-game-preview-3) Your device does not support video playback. Signed message argument ----------------------- [Section titled “Signed message argument”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#signed-message-argument) The signed message argument allows a player to send an argument in the form of a **signed message** to the server. This signed message is a special type - it allows the server to send that message, without the ability to directly modify it, to any player. The visible difference is that unsigned messages have a white bar at the left, whilst signed messages don’t. A signed message argument returns a `SignedMessageResolver`. In order to call its `#resolve` method, you have to pass in two parameters: * The argument name * The `CommandContext` object The resolved value is a `CompletableFuture`, whose [`SignedMessage`](https://jd.advntr.dev/api/latest/net/kyori/adventure/chat/SignedMessage.html) value you can handle using `thenAccept(Consumer)`. Inside of the consumer, you can send the signed message to players or work with it in other ways. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#example-usage-4) public static LiteralCommandNode signedMessageArgument() { return Commands.literal("signedmessage") .then(Commands.argument("target", ArgumentTypes.player()) .then(Commands.argument("message", ArgumentTypes.signedMessage()) .executes(MinecraftArguments::executeSignedMessageCommand))) .build();} private static int executeSignedMessageCommand(final CommandContext ctx) throws CommandSyntaxException { final Player target = ctx.getArgument("target", PlayerSelectorArgumentResolver.class).resolve(ctx.getSource()).getFirst(); final SignedMessageResolver messageResolver = ctx.getArgument("message", SignedMessageResolver.class); messageResolver.resolveSignedMessage("message", ctx).thenAccept(msg -> { target.sendMessage(msg, ChatType.CHAT.bind(ctx.getSource().getSender().name())); }); return Command.SINGLE_SUCCESS;} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/adventure/#in-game-preview-4) Your device does not support video playback. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Registry | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/arguments/registry/#_top) Registry ======== Registries in Minecraft hold all sort of information - possible item or block types, enchantments, potion effects, … and more! There are two types of registry arguments: `resource` and `resourceKey`. The main difference between those arguments is the return value: The `resource` argument returns the parsed value, whilst the `resourceKey` only returns a `TypedKey`, which you can use to retrieve the value yourself. Resource argument ----------------- [Section titled “Resource argument”](https://docs.papermc.io/paper/dev/command-api/arguments/registry/#resource-argument) Just like any other argument, you can get a `ArgumentType` reference to it using `ArgumentTypes.resource(RegistryKey)`. A selection of possible registry keys can be found below. They are accessed in a static context using the [`RegistryKey`](https://jd.papermc.io/paper/io/papermc/paper/registry/RegistryKey.html) interface. Each entry in `RegistryKey` returns a `RegistryKey`. The `` generic parameter here describes the return type. This means that if we were to retrieve [`RegistryKey.ITEM`](https://jd.papermc.io/paper/io/papermc/paper/registry/RegistryKey.html#ITEM) , the return type would be an `ItemType`, since it is defined as follows: public sealed interface RegistryKey extends Keyed permits RegistryKeyImpl { // ... RegistryKey ITEM = RegistryKeyImpl.create("item"); // ...} And really, there isn’t much more to it. For that exact reason, here is an example on the implementation of such an argument: public static LiteralCommandNode enchantmentRegistry() { return Commands.literal("enchants-registry") .then(Commands.argument("enchantment", ArgumentTypes.resource(RegistryKey.ENCHANTMENT)) .executes(ctx -> { final Enchantment enchantment = ctx.getArgument("enchantment", Enchantment.class); if (ctx.getSource().getExecutor() instanceof Player player) { final ItemStack stack = player.getInventory().getItemInMainHand(); stack.addUnsafeEnchantment(enchantment, 10); ctx.getSource().getSender().sendRichMessage("Enchanted 's with !", Placeholder.component("player", player.name()), Placeholder.component("item", Component.translatable(stack)), Placeholder.component("enchantment", enchantment.displayName(10)) ); return Command.SINGLE_SUCCESS; } ctx.getSource().getSender().sendRichMessage("This command requires a player!"); return Command.SINGLE_SUCCESS; })) .build();} We define an `enchantment` argument using a enchantment registry key resource and retrieve the value of that using `ctx.getArgument("enchantment", Enchantment.class)`. Finally, we enchant the item of the executing player’s hand with whatever enchantment the sender chose at level 10 and send a success message. Here is how it looks in-game: Your device does not support video playback. Resource key argument --------------------- [Section titled “Resource key argument”](https://docs.papermc.io/paper/dev/command-api/arguments/registry/#resource-key-argument) For the client, there is barely any difference between the using `ArgumentTypes.resource` or `ArgumentTypes.resourceKey`. The only difference is that using `ArgumentTypes.resourceKey` does not provide **error checking**. We can visualize this using `RegistryKey.ITEM`. Here is the tab completion when using `ArgumentTypes.resource(RegistryKey.ITEM)`: Your device does not support video playback. And here is the tab completion when using `ArgumentTypes.resourceKey(RegistryKey.ITEM)`: Your device does not support video playback. The resource argument provides a much cleaner user experience, whilst the `resourceKey` argument has one very important use case: You get the raw `TypedKey` returned as an argument result. This object is particularly useful, as it provides all information required to be able to retrieve a value from a registry yourself. ### Direct code comparison [Section titled “Direct code comparison”](https://docs.papermc.io/paper/dev/command-api/arguments/registry/#direct-code-comparison) Here is a simple code snipped on how one could use the `RegistryKey.ITEM` registry with a `resource` argument type: Commands.argument("item", ArgumentTypes.resource(RegistryKey.ITEM)) .executes(ctx -> { final ItemType item = ctx.getArgument("item", ItemType.class); if (ctx.getSource().getExecutor() instanceof Player player) { player.getInventory().addItem(item.createItemStack()); } return Command.SINGLE_SUCCESS; }); Here is the same code, using a `resourceKey` argument type. Instead of directly retrieving the argument using `ctx.getArgument("item", TypedKey.class)`, we instead use the [`RegistryArgumentExtractor`](https://jd.papermc.io/paper/io/papermc/paper/command/brigadier/argument/RegistryArgumentExtractor.html) to retrieve our `TypedKey`. Commands.argument("item", ArgumentTypes.resourceKey(RegistryKey.ITEM)) .executes(ctx -> { final TypedKey itemKey = RegistryArgumentExtractor.getTypedKey(ctx, RegistryKey.ITEM, "item"); ItemType item = RegistryAccess.registryAccess().getRegistry(itemKey.registryKey()).get(itemKey.key()); if (item == null) { ctx.getSource().getSender().sendRichMessage("Please provide a valid item!"); return Command.SINGLE_SUCCESS; } if (ctx.getSource().getExecutor() instanceof Player player) { player.getInventory().addItem(item.createItemStack()); } return Command.SINGLE_SUCCESS; }) ### Using a TypedKey [Section titled “Using a TypedKey”](https://docs.papermc.io/paper/dev/command-api/arguments/registry/#using-a-typedkey) First, in order to get the correct registry, you can run `RegistryAccess#getRegistry(RegistryKey)`. In order to get a `RegistryAccess`, you can just use the static `RegistryAccess.registryAccess()` method. The `RegistryKey` is retrieved using `TypedKey#registryKey()`. Now, in order to get the final value `T`, you can run `Registry#get(Key)`, where the key can be retrieved using `TypedKey#key()`. This will return the backing instance from that resource key or null, if no value has been found. ### Use case over resource argument [Section titled “Use case over resource argument”](https://docs.papermc.io/paper/dev/command-api/arguments/registry/#use-case-over-resource-argument) The main use case for this argument type is the ability to store the key (the value returned to you by `TypedKey#key`). If you want to be able to store the exact user input and be able to retrieve the backed instance without much trouble, that is the way to do it. Registry key types ------------------ [Section titled “Registry key types”](https://docs.papermc.io/paper/dev/command-api/arguments/registry/#registry-key-types) You can get a list of all registry key types and their return values on the [`RegistryKey` Javadocs](https://jd.papermc.io/paper/io/papermc/paper/registry/RegistryKey.html) . Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Debugging your plugin | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/debugging/#_top) Debugging your plugin ===================== Debugging your plugin is vital to being able to fix bugs and issues in your plugin. This page will cover some of the most common debugging techniques. Printing to the console ----------------------- [Section titled “Printing to the console”](https://docs.papermc.io/paper/dev/debugging/#printing-to-the-console) One of the most common debugging techniques is to print to the console. This is likely something you’ve done before, as it’s very simple. This has a few downsides, though. It can be hard to find the print statements in the console, and it can be hard to remove them all when you’re done debugging. Most notably, you have to recompile your plugin and restart the server to add or remove debugging. When debugging, you can use `System.out.println("");` to print to the console. It is recommended to use your plugin’s logger instead though, as it will be easier to know which plugin the log has come from. This can be done simply with: plugin.getComponentLogger().debug(Component.text("SuperDuperBad Thing has happened")); Using a remote debugger ----------------------- [Section titled “Using a remote debugger”](https://docs.papermc.io/paper/dev/debugging/#using-a-remote-debugger) A debugger is a tool that allows you to pause your code at a certain point and inspect the values of variables. This can be very useful for finding out why your code isn’t working as expected and also for finding out where your code is going wrong. ### Setting up the debugger [Section titled “Setting up the debugger”](https://docs.papermc.io/paper/dev/debugging/#setting-up-the-debugger) To use a debugger, you need to set up your IDE to use it. This is different for each IDE, but for the sake of this guide, we will be using IntelliJ IDEA. To set up a debugger in IntelliJ, you need to create a new run configuration. You can do this by clicking the dropdown next to the run button and clicking `Edit Configurations...`: ![](https://docs.papermc.io/_astro/config_dropdown.BFxL9k7t_Zf8FGm.webp) Then, click the `+` button in the top left and select `Remote JVM Debug`. You can then name the configuration whatever you want, and click `Apply`: ![](https://docs.papermc.io/_astro/config_add.BZo3OiyP_Z2mKEN9.webp) Finally, copy the command line arguments from the window, and paste these into your server’s startup script. These will go after the `java` command and before `-jar`. Once you have done this, you can click `OK`. For example: java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -jar paper-26.1.2.jar nogui Once your server is running, you can use the bug icon in the top right to connect your debugger to the server: ![](https://docs.papermc.io/_astro/debugger_connect.mnUOoaKC_ZDRJ8d.webp) #### Using the debugger [Section titled “Using the debugger”](https://docs.papermc.io/paper/dev/debugging/#using-the-debugger) Let’s say we have this code: @EventHandlerpublic void onPlayerMove(PlayerMoveEvent event) { Player player = event.getPlayer(); Location location = player.getLocation(); if (location.getWorld() == null) return; if (location.getWorld().getEnvironment() == World.Environment.NETHER) { player.sendMessage("You are in the nether!"); }} You can add a breakpoint to the line by clicking on the line number: ![](https://docs.papermc.io/_astro/add_breakpoints.Dgq1Prxb_Z1pPHSQ.webp) This will pause the code when it reaches that line. You can then use the debugger to inspect the values of variables: ![](https://docs.papermc.io/_astro/debugger_use.Cd360zfH_2kA1zG.webp) You can inspect the values of each of the variables in the current scope. You can also use the buttons in the top to step from one breakpoint to the next. If needed, you can also use the text box at the top to evaluate expressions for debugging purposes. ### Using direct debugging [Section titled “Using direct debugging”](https://docs.papermc.io/paper/dev/debugging/#using-direct-debugging) Direct debugging will allow you to run the server directly from your IDE, and will allow you to use breakpoints and step through your code. We can achieve this by using [JPenilla’s Gradle plugin](https://github.com/jpenilla/run-task) to run the server directly from the IDE. See [here](https://github.com/jpenilla/run-task#basic-usage) for instructions on how to set up the plugin. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Suggestions | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/basics/argument-suggestions/#_top) Suggestions =========== Sometimes, you want to send your own suggestions to users. For this, you can use the `suggests(SuggestionProvider)` method when declaring arguments. Examining `SuggestionProvider` --------------------------------- [Section titled “Examining SuggestionProvider”](https://docs.papermc.io/paper/dev/command-api/basics/argument-suggestions/#examining-suggestionproviders) The `SuggestionProvider` interface is defined as follows: @FunctionalInterfacepublic interface SuggestionProvider { CompletableFuture getSuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException;} Similar to other classes or interfaces with a `` generic parameter, for Paper, this is usually a `CommandSourceStack`. Furthermore, similar to the `Command` interface, this is a functional interface, which means that instead of passing in a class which implements this interface, we can just pass a lambda statement or a method reference. Our lambda consists of two parameters, `CommandContext` and `SuggestionsBuilder`, and expects to have a `CompletableFuture` returned. A very simple lambda for our `suggests` method might look like this: Commands.argument("name", StringArgumentType.word()) .suggests((ctx, builder) -> builder.buildFuture()); This example obviously does not suggest anything, as we haven’t added any suggestions yet. The `SuggestionsBuilder` ------------------------ [Section titled “The SuggestionsBuilder”](https://docs.papermc.io/paper/dev/command-api/basics/argument-suggestions/#the-suggestionsbuilder) The `SuggestionsBuilder` has a few methods we can use to construct our suggestions: ### Input retrieval [Section titled “Input retrieval”](https://docs.papermc.io/paper/dev/command-api/basics/argument-suggestions/#input-retrieval) The first type of methods we will cover are the input retrieval methods: `getInput()`, `getStart()`, `getRemaining()`, and `getRemainingLowerCase()`. The following table displays what each returns with the following input typed in the chat bar: `/customsuggestions Asumm13Text`. | Method | Return Value | Description | | --- | --- | --- | | getInput() | /customsuggestions Asumm13Text | The full chat input | | getStart() | 19 | The index of the first character of the argument’s input | | getRemaining() | Asumm13Text | The input for the current argument | | getRemainingLowerCase() | asumm13text | The input for the current argument, lowercased | ### Suggestions [Section titled “Suggestions”](https://docs.papermc.io/paper/dev/command-api/basics/argument-suggestions/#suggestions) The following overloads of the `SuggestionsBuilder#suggest` method add values that will be send to the client as argument suggestions: | Overload | Description | | --- | --- | | suggest(String) | Adds a String to the suggestions | | suggest(String, Message) | Adds a String with a tooltip to the suggestions | | suggest(int) | Adds an int to the suggestions | | suggest(int, Message) | Adds an int with a tooltip to the suggestions | There are two ways of retrieving a `Message` instance: * Using `LiteralMessage`, which can be used for basic, non-formatted text. * Using the `MessageComponentSerializer`, which can be used to serialize `Component` objects into `Message` objects. For example, if you add a suggestion like this: builder.suggest("suggestion", MessageComponentSerializer.message().serialize( MiniMessage.miniMessage().deserialize("Suggestion tooltip"))); It will look like this on the client: ![](https://docs.papermc.io/_astro/suggestion-tooltip.Coi5XvhS_Z2edIAr.webp) ### Building [Section titled “Building”](https://docs.papermc.io/paper/dev/command-api/basics/argument-suggestions/#building) There are two methods we can use to build our `Suggestions` object. The only difference between those is that one directly returns the finished `Suggestions` object, whilst the other one returns a `CompletableFuture`. The reason for these two methods is that `SuggestionProvider` expects the return value to be `CompletableFuture`. This for once allows for constructing your suggestions asynchronously inside a `CompletableFuture.supplyAsync(Supplier)` statement, or synchronously directly inside our lambda and returning the final `Suggestions` object asynchronously. Here are the same suggestions declared in the two different ways mentioned above: // Here, you are safe to use all Paper APICommands.argument("name", StringArgumentType.word()) .suggests((ctx, builder) -> { builder.suggest("first"); builder.suggest("second"); return builder.buildFuture(); }); // Here, most Paper API is not usableCommands.argument("name", StringArgumentType.word()) .suggests((ctx, builder) -> CompletableFuture.supplyAsync(() -> { builder.suggest("first"); builder.suggest("second"); return builder.build(); })); Example: Suggesting amounts in a give item command -------------------------------------------------- [Section titled “Example: Suggesting amounts in a give item command”](https://docs.papermc.io/paper/dev/command-api/basics/argument-suggestions/#example-suggesting-amounts-in-a-give-item-command) In commands, where you give players items, you oftentimes include an amount argument. We could suggest `1`, `16`, `32`, and `64` as common amounts for items given. The command implementation could look like this: @NullMarkedpublic class SuggestionsTest { public static LiteralCommandNode constructGiveItemCommand() { // Create new command: /giveitem return Commands.literal("giveitem") // Require a player to execute the command .requires(ctx -> ctx.getExecutor() instanceof Player) // Declare a new ItemStack argument .then(Commands.argument("item", ArgumentTypes.itemStack()) // Declare a new integer argument with the bounds of 1 to 99 .then(Commands.argument("amount", IntegerArgumentType.integer(1, 99)) // Here, we use method references, since otherwise, our command definition would grow too big .suggests(SuggestionsTest::getAmountSuggestions) .executes(SuggestionsTest::executeCommandLogic) ) ) .build(); } private static CompletableFuture getAmountSuggestions(final CommandContext ctx, final SuggestionsBuilder builder) { // Suggest 1, 16, 32, and 64 to the user when they reach the 'amount' argument builder.suggest(1); builder.suggest(16); builder.suggest(32); builder.suggest(64); return builder.buildFuture(); } private static int executeCommandLogic(final CommandContext ctx) { // We know that the executor will be a player, so we can just silently return if (!(ctx.getSource().getExecutor() instanceof Player player)) { return Command.SINGLE_SUCCESS; } // If the player has no empty slot, we tell the player that they have no free inventory space final int firstEmptySlot = player.getInventory().firstEmpty(); if (firstEmptySlot == -1) { player.sendRichMessage("You do not have enough space in your inventory!"); return Command.SINGLE_SUCCESS; } // Retrieve our argument values final ItemStack item = ctx.getArgument("item", ItemStack.class); final int amount = IntegerArgumentType.getInteger(ctx, "amount"); // Set the item's amount and give it to the player item.setAmount(amount); player.getInventory().setItem(firstEmptySlot, item); // Send a confirmation message player.sendRichMessage("You have been given x !", Placeholder.component("amount", Component.text(amount)), Placeholder.component("item", Component.translatable(item).hoverEvent(item)) ); return Command.SINGLE_SUCCESS; }} And here is how the command looks in-game: Your device does not support video playback. Example: Filtering by user input -------------------------------- [Section titled “Example: Filtering by user input”](https://docs.papermc.io/paper/dev/command-api/basics/argument-suggestions/#example-filtering-by-user-input) If you have multiple values, it is suggested that you filter your suggestions by what the user has already put in. For this, we can declare the following, simple command as a test: public static LiteralCommandNode constructStringSuggestionsCommand() { final List names = List.of("Alex", "Andreas", "Stephanie", "Sophie", "Emily"); return Commands.literal("selectname") .then(Commands.argument("name", StringArgumentType.word()) .suggests((ctx, builder) -> { names.stream() .filter(entry -> entry.toLowerCase().startsWith(builder.getRemainingLowerCase())) .forEach(builder::suggest); return builder.buildFuture(); }) ).build();} This simple setup filters suggestions by user input, providing a smooth user experience when running the command: Your device does not support video playback. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Teleportation | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/entity-teleport/#_top) Teleportation ============= Entities can be instantaneously teleported to specific positions, synchronously and asynchronously with the [`teleport`](https://jd.papermc.io/paper/org/bukkit/entity/Entity.html#teleport(org.bukkit.Location)) and [`teleportAsync`](https://jd.papermc.io/paper/org/bukkit/entity/Entity.html#teleportAsync(org.bukkit.Location)) API. entity.teleport(location); // loads chunks synchronously and teleports the entity entity.teleportAsync(location).thenAccept(success -> { // loads chunks asynchronously and teleports the entity // this code is ran when the teleport completes // the Future is completed on the main thread, so it is safe to use the API here if (success) { // the entity was teleported successfully! }}); Look at ------- [Section titled “Look at”](https://docs.papermc.io/paper/dev/entity-teleport/#look-at) The [`lookAt`](https://jd.papermc.io/paper/org/bukkit/entity/Player.html#lookAt(org.bukkit.entity.Entity,io.papermc.paper.entity.LookAnchor,io.papermc.paper.entity.LookAnchor)) API allows you to make a player look at a certain position or entity. player.lookAt( position, LookAnchor.EYES // the player's eyes will be facing the position); player.lookAt( entity, LookAnchor.EYES // the player's eyes will be facing the entity LookAnchor.FEET // the player will be facing the entity's feet); Teleport flags -------------- [Section titled “Teleport flags”](https://docs.papermc.io/paper/dev/entity-teleport/#teleport-flags) Teleport flags offer a way to teleport entities whilst being able to customize behavior. This allows you to do things like teleport players using relative flags and being able to retain passengers. All available teleport flags can be found in the [`TeleportFlag`](https://jd.papermc.io/paper/io/papermc/paper/entity/TeleportFlag.html) class. ### Relative teleportation [Section titled “Relative teleportation”](https://docs.papermc.io/paper/dev/entity-teleport/#relative-teleportation) Teleport a player relatively, preventing velocity from being reset in the X, Y and Z axes. player.teleport( location, TeleportFlag.Relative.VELOCITY_X, TeleportFlag.Relative.VELOCITY_Y, TeleportFlag.Relative.VELOCITY_Z); ### Retaining passengers [Section titled “Retaining passengers”](https://docs.papermc.io/paper/dev/entity-teleport/#retaining-passengers) Teleport an entity with the [`RETAIN_PASSENGERS`](https://jd.papermc.io/paper/io/papermc/paper/entity/TeleportFlag.EntityState.html#RETAIN_PASSENGERS) flag, allowing its passengers to be transferred with the entity. entity.teleport(location, TeleportFlag.EntityState.RETAIN_PASSENGERS); Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # bukkit.yml | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/reference/bukkit-configuration/#_top) bukkit.yml ========== settings: [#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings) allow-end: true[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_allow_end) Whether to load end-type dimensions. warn-on-overload: true[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_warn_on_overload) Allows disabling the “Can’t keep up!” message. permissions-file: permissions.yml[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_permissions_file) File to load server permissions from. Use of this feature has mostly been replaced by permission plugins. update-folder: update[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_update_folder) Path to replace new plugin versions with. See [Updating Plugins](https://docs.papermc.io/paper/updating#step-2-update-plugins) for more information. plugin-profiling: false[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_plugin_profiling) This option does not operate, as it is disabled by a Paper patch. connection-throttle: 4000[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_connection_throttle) How long of a delay to enforce between connections from an IP address. Measured in milliseconds since last attempt. query-plugins: true[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_query_plugins) Whether to send plugins in the GS4 Query protocol response. deprecated-verbose: default[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_deprecated_verbose) Whether to warn for use of deprecated events. If “default”, the warning is printed if annotated with `@Warning(true)`. Ignored if system property [paper.alwaysPrintWarningState](https://docs.papermc.io/paper/reference/system-properties#paperalwaysprintwarningstate) is true. Valid values are “true”, “false”, or “default”. shutdown-message: Server closed[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_shutdown_message) The kick message for the player when the server shuts down. The message is formatted with legacy ”§” style formatting. minimum-api: none[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_minimum_api) Minimum plugin [api-version](https://docs.papermc.io/paper/dev/plugin-yml#api-version) . A string containing the server version, from `1.13` to `26.1.2`. If below this, or not specified, the plugin is prevented from loading. use-map-color-cache: true[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_use_map_color_cache) Whether to build and save mappings from RGB colors to the closest map palette color. world-container: N/A[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#settings_world_container) Specifies the path to the folder where world files are saved. By default, this is the folder where the server JAR file is located. Note: Worlds must be manually moved to this folder for the server to recognize them. spawn-limits: [#](https://docs.papermc.io/paper/reference/bukkit-configuration/#spawn_limits) monsters: 70[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#spawn_limits_monsters) Set the spawn-limits for monsters. This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_spawn_limits_monster) . animals: 10[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#spawn_limits_animals) Set the spawn-limits for animals. This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_spawn_limits_creature) . water-animals: 5[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#spawn_limits_water_animals) Set the spawn-limits for water animals. This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_spawn_limits_water_creature) . water-ambient: 20[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#spawn_limits_water_ambient) Set the spawn-limits for water ambient mobs. This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_spawn_limits_water_ambient) . water-underground-creature: 5[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#spawn_limits_water_underground_creature) Set the spawn-limits for water underground creatures. This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_spawn_limits_underground_water_creature) . axolotls: 5[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#spawn_limits_axolotls) Set the spawn-limits for axolotls. This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_spawn_limits_axolotls) . ambient: 15[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#spawn_limits_ambient) Set the spawn-limits for ambient mobs. This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_spawn_limits_ambient) . chunk-gc: [#](https://docs.papermc.io/paper/reference/bukkit-configuration/#chunk_gc) period-in-ticks: 600[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#chunk_gc_period_in_ticks) How long chunks loaded by plugins should last for. Capped by Paper to be 20 ticks (1 second). ticks-per: [#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per) animal-spawns: 400[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per_animal_spawns) Number of ticks between each passive creature (animal) spawn attempt. Set to -1 to use [the Vanilla default](https://minecraft.wiki/w/Mob_spawning#Spawn_cycle) . This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_ticks_per_spawn_creature) . monster-spawns: 1[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per_monster_spawns) Number of ticks between each hostile monster spawn attempt. Set to -1 to use [the Vanilla default](https://minecraft.wiki/w/Mob_spawning#Spawn_cycle) . This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_ticks_per_spawn_monster) . water-spawns: 1[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per_water_spawns) Number of ticks between each water creature spawn attempt. Set to -1 to use [the Vanilla default](https://minecraft.wiki/w/Mob_spawning#Spawn_cycle) . This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_ticks_per_spawn_water_creature) . water-ambient-spawns: 1[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per_water_ambient_spawns) Number of ticks between each ambient water mob spawn attempt. Set to -1 to use [the Vanilla default](https://minecraft.wiki/w/Mob_spawning#Spawn_cycle) . This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_ticks_per_spawn_water_ambient) . water-underground-creature-spawns: 1[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per_water_underground_creature_spawns) Number of ticks between each underground water creatures spawn attempt. Set to -1 to use [the Vanilla default](https://minecraft.wiki/w/Mob_spawning#Spawn_cycle) . This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_ticks_per_spawn_underground_water_creature) . axolotl-spawns: 1[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per_axolotl_spawns) Number of ticks between each axolotl spawn attempt. Set to -1 to use [the Vanilla default](https://minecraft.wiki/w/Mob_spawning#Spawn_cycle) . This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_ticks_per_spawn_axolotls) . ambient-spawns: 1[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per_ambient_spawns) Number of ticks between each ambient mob spawn attempt. Set to -1 to use [the Vanilla default](https://minecraft.wiki/w/Mob_spawning#Spawn_cycle) . This can be overridden by the [Paper world config](https://docs.papermc.io/paper/reference/world-configuration#entities_spawning_ticks_per_spawn_ambient) . autosave: 6000[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#ticks_per_autosave) Number of ticks between each full auto-save. Set to -1 to disable auto-save. aliases: now-in-commands.yml[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#aliases) Static value from converting old versions to the new commands.yml format. worlds: [#](https://docs.papermc.io/paper/reference/bukkit-configuration/#worlds) : [#](https://docs.papermc.io/paper/reference/bukkit-configuration/#worlds__world_) biome-provider: N/A[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#worlds__world__biome_provider) The biome provider to use for this world. Plugins must register a `BiomeProvider` to be used here. The format is _plugin-name:extra-parameters_ or _plugin-name_ if no extra parameters are needed. The plugin name is as defined in the `plugin.yml` or `paper-plugin.yml`. generator: N/A[#](https://docs.papermc.io/paper/reference/bukkit-configuration/#worlds__world__generator) The generator to use for this world. Plugins must register a `ChunkGenerator` to be used here. The format is _plugin-name:extra-parameters_ or _plugin-name_ if no extra parameters are needed. The plugin name is as defined in the `plugin.yml` or `paper-plugin.yml`. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Comparison | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/misc/comparison-bukkit-brigadier/#_top) Comparison ========== Registering commands -------------------- [Section titled “Registering commands”](https://docs.papermc.io/paper/dev/command-api/misc/comparison-bukkit-brigadier/#registering-commands) ### The old Bukkit way [Section titled “The old Bukkit way”](https://docs.papermc.io/paper/dev/command-api/misc/comparison-bukkit-brigadier/#the-old-bukkit-way) In order to register Bukkit commands, you would define a class that extends `BukkitCommand`, and implements the `execute(...)` and `tabComplete(...)` methods. This might look like this: package your.package.name; import org.bukkit.Bukkit;import org.bukkit.command.CommandSender;import org.bukkit.command.defaults.BukkitCommand;import org.bukkit.entity.Player;import org.jspecify.annotations.NullMarked; import java.util.List; @NullMarkedpublic class BukkitPartyCommand extends BukkitCommand { public BukkitPartyCommand(String name, String description, String usageMessage, List aliases) { super(name, description, usageMessage, aliases); } @Override public boolean execute(CommandSender sender, String commandLabel, String[] args) { if (args.length == 0) { sender.sendPlainMessage("Please provide a player!"); return false; } final Player targetPlayer = Bukkit.getPlayer(args[0]); if (targetPlayer == null) { sender.sendPlainMessage("Please provide a valid player!"); return false; } targetPlayer.sendPlainMessage(sender.getName() + " started partying with you!"); sender.sendPlainMessage("You are now partying with " + targetPlayer.getName() + "!"); return true; } @Override public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { if (args.length == 1) { return Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(); } return List.of(); }} After that, you can define your command like this: this.getServer().getCommandMap().register( this.getName().toLowerCase(), new BukkitPartyCommand("bukkitparty", "Have a party", "/bukkitparty ", List.of())); As you can see, you have to do a lot of manual checking in order to register a single, very simple command. But how does the Brigadier API do it? ### The new Paper way [Section titled “The new Paper way”](https://docs.papermc.io/paper/dev/command-api/misc/comparison-bukkit-brigadier/#the-new-paper-way) First, we need to retrieve a `LiteralCommandNode`. That’s a special Brigadier class that holds some sort of [command tree](https://docs.papermc.io/paper/dev/command-api/basics/command-tree) . In our case, it is the root of our command. We can do that by running `Commands.literal(final String literal)`, which returns a `LiteralArgumentBuilder`, where we can define some arguments and executors. Once we are done, we can call `LiteralArgumentBuilder#build()` to retrieve our build `LiteralCommandNode`, which we can then register. That sounds complicated at first, but once you see it in action, it looks less terrifying: public static LiteralCommandNode createCommand(final String commandName) { return Commands.literal(commandName) .then(Commands.argument("target", ArgumentTypes.player()) .executes(ctx -> { final PlayerSelectorArgumentResolver playerSelector = ctx.getArgument("target", PlayerSelectorArgumentResolver.class); final Player targetPlayer = playerSelector.resolve(ctx.getSource()).getFirst(); final CommandSender sender = ctx.getSource().getSender(); targetPlayer.sendPlainMessage(sender.getName() + " started partying with you!"); sender.sendPlainMessage("You are now partying with " + targetPlayer.getName() + "!"); return Command.SINGLE_SUCCESS; })) .build();} Each `.then(...)` defines a new branch in our tree, which can either be a literal (`Commands.literal(String)`) or an argument (`Commands.argument(String, ArgumentType)`). Each branch may or may not define an `.executes(Command)` executor. This is where all the logic happens. We will take a closer look at that in different pages, but for now, how do we register it? Paper uses a `LifecycleEventManager` system. In a nutshell, that is a way to register commands (or tags) that get loaded each time the server reloads its resources, like using /reload. Registering our command looks like this: this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> { commands.registrar().register(PaperPartyCommand.createCommand("paperparty"), "Have a nice party");}); And we are done! As you can see here, both commands do the same thing: ![](https://docs.papermc.io/_astro/bukkitparty-command.Bui70wtw_Z2aJGq5.webp) ![](https://docs.papermc.io/_astro/paperparty-command.CPdWND_7_Z2x0ODD.webp) Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Reading stacktraces | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/reading-stacktraces/#_top) Reading stacktraces =================== What is a stacktrace? --------------------- [Section titled “What is a stacktrace?”](https://docs.papermc.io/paper/dev/reading-stacktraces/#what-is-a-stacktrace) In Java, a stacktrace shows the call stack of a thread. The call stack is the path of execution that led to the current point in the program. Usually, the stacktrace will be printed to the console when an exception is not handled correctly. Stacktraces are a useful tool for debugging your code. They show you the exact line of code that caused an error, and the line of code that called that line of code, and so on. This is useful because it allows you to see the exact path of execution that led to the error. ### Example [Section titled “Example”](https://docs.papermc.io/paper/dev/reading-stacktraces/#example) Here is an example of a stacktrace, which has been caused due to a `NullPointerException`: [15:20:42 ERROR]: Could not pass event PluginEnableEvent to TestPlugin v1.0java.lang.NullPointerException: Cannot invoke "Object.toString()" because "player" is null at io.papermc.testplugin.TestPlugin.onPluginEnable(TestPlugin.java:23) ~[TestPlugin-1.0-SNAPSHOT.jar:?] at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor1.execute(Unknown Source) ~[?:?] at org.bukkit.plugin.EventExecutor$2.execute(EventExecutor.java:77) ~[paper-api-1.20.2-R0.1-SNAPSHOT.jar:?] at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:81) ~[paper-api-1.20.2-R0.1-SNAPSHOT.jar:git-Paper-49] at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[paper-api-1.20.2-R0.1-SNAPSHOT.jar:?] at io.papermc.paper.plugin.manager.PaperEventManager.callEvent(PaperEventManager.java:54) ~[paper-1.20.2.jar:git-Paper-49] at io.papermc.paper.plugin.manager.PaperPluginManagerImpl.callEvent(PaperPluginManagerImpl.java:126) ~[paper-1.20.2.jar:git-Paper-49] at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:615) ~[paper-api-1.20.2-R0.1-SNAPSHOT.jar:?] at io.papermc.paper.plugin.manager.PaperPluginInstanceManager.enablePlugin(PaperPluginInstanceManager.java:200) ~[paper-1.20.2.jar:git-Paper-49] at io.papermc.paper.plugin.manager.PaperPluginManagerImpl.enablePlugin(PaperPluginManagerImpl.java:104) ~[paper-1.20.2.jar:git-Paper-49] at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:507) ~[paper-api-1.20.2-R0.1-SNAPSHOT.jar:?] at org.bukkit.craftbukkit.v1_20_R2.CraftServer.enablePlugin(CraftServer.java:636) ~[paper-1.20.2.jar:git-Paper-49] at org.bukkit.craftbukkit.v1_20_R2.CraftServer.enablePlugins(CraftServer.java:547) ~[paper-1.20.2.jar:git-Paper-49] at net.minecraft.server.MinecraftServer.loadWorld0(MinecraftServer.java:636) ~[paper-1.20.2.jar:git-Paper-49] at net.minecraft.server.MinecraftServer.loadLevel(MinecraftServer.java:435) ~[paper-1.20.2.jar:git-Paper-49] at net.minecraft.server.dedicated.DedicatedServer.initServer(DedicatedServer.java:308) ~[paper-1.20.2.jar:git-Paper-49] at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1101) ~[paper-1.20.2.jar:git-Paper-49] at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:318) ~[paper-1.20.2.jar:git-Paper-49] at java.lang.Thread.run(Thread.java:833) ~[?:?] * Firstly, we can see that this certain error occurred when a [`PluginEnableEvent`](https://jd.papermc.io/paper/org/bukkit/event/server/PluginEnableEvent.html) was being handled by the `TestPlugin`. * Then we can see on the second line, the cause of the exception: > `java.lang.NullPointerException: Cannot invoke "Object.toString()" because "player" is null` This tells us that the exception was caused by a [`NullPointerException`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/NullPointerException.html) , and that the exception was caused because we tried to call the `toString()` method on a null “player” object. * From here, as we work down the stacktrace, we can see the exact path of execution that led to the error. In this case, the next line of the stacktrace is: > `at io.papermc.testplugin.TestPlugin.onPluginEnable(TestPlugin.java:23) ~[TestPlugin-1.0-SNAPSHOT.jar:?]` Which tells us that the error was thrown at line 23 of `TestPlugin.java`. * You can continue to work down the stacktrace, and see the exact path of execution that led to the error. In this case, it is server internals, so we can generally ignore it. Omitted stacktraces ------------------- [Section titled “Omitted stacktraces”](https://docs.papermc.io/paper/dev/reading-stacktraces/#omitted-stacktraces) In JDK 5, the JVM started to omit stacktraces for certain exceptions. This was common when the JVM had optimized the code, and you could get `NullPointerException`s without a stacktrace. In order to fix this, you can pass the `-XX:-OmitStackTraceInFastThrow` flag to the JVM: java -XX:-OmitStackTraceInFastThrow -jar paper.jar Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Listeners | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/event-listeners/#_top) Listeners ========= Events are an efficient way to listen for specific actions that happen in the game. They can be called by the server, or by plugins. These are called by the server or plugins when something happens, such as a player joining the server, or a block being broken. Plugins are able to call custom events, such as a player completing a quest, for other plugins to listen for. Your listener class ------------------- [Section titled “Your listener class”](https://docs.papermc.io/paper/dev/event-listeners/#your-listener-class) To listen for events, you need to create a class that implements [`Listener`](https://jd.papermc.io/paper/org/bukkit/event/Listener.html) . This class can be called anything you want, but it is recommended to name it something related to the events you are listening for. public class ExampleListener implements Listener { // ...} `@EventHandler` --------------- [Section titled “@EventHandler”](https://docs.papermc.io/paper/dev/event-listeners/#eventhandler) To listen for an event, you need to create a method that is annotated with [`@EventHandler`](https://jd.papermc.io/paper/org/bukkit/event/EventHandler.html) . This method can be named anything you want, but it is recommended to name it something meaningful related to the event it is listening for. The listener method ------------------- [Section titled “The listener method”](https://docs.papermc.io/paper/dev/event-listeners/#the-listener-method) The method body does not need to return any data, for this reason, use void as the return type. Listeners take in a single parameter, which is the event that is being listened to. public class ExampleListener implements Listener { @EventHandler public void onPlayerMove(PlayerMoveEvent event) { // ... }} Registering the listener ------------------------ [Section titled “Registering the listener”](https://docs.papermc.io/paper/dev/event-listeners/#registering-the-listener) To register the listener, you need to call `Bukkit.getPluginManager().registerEvents()` and pass in your listener class instance and an instance of your plugin. This will register your listener class and allow it to listen for events. This is commonly done in the `onEnable()` method of your plugin so that it is registered when the server starts ticking. public class ExamplePlugin extends JavaPlugin { @Override public void onEnable() { getServer().getPluginManager().registerEvents(new ExampleListener(), this); }} Event priority -------------- [Section titled “Event priority”](https://docs.papermc.io/paper/dev/event-listeners/#event-priority) You can also specify the priority of the event. public class ExampleListener implements Listener { @EventHandler(priority = EventPriority.HIGH) public void onPlayerMove(PlayerMoveEvent event) { // ... }} There are six different priorities that you can use: * [`EventPriority.LOWEST`](https://jd.papermc.io/paper/org/bukkit/event/EventPriority.html#LOWEST) * [`EventPriority.LOW`](https://jd.papermc.io/paper/org/bukkit/event/EventPriority.html#LOW) * [`EventPriority.NORMAL`](https://jd.papermc.io/paper/org/bukkit/event/EventPriority.html#NORMAL) * [`EventPriority.HIGH`](https://jd.papermc.io/paper/org/bukkit/event/EventPriority.html#HIGH) * [`EventPriority.HIGHEST`](https://jd.papermc.io/paper/org/bukkit/event/EventPriority.html#HIGHEST) * [`EventPriority.MONITOR`](https://jd.papermc.io/paper/org/bukkit/event/EventPriority.html#MONITOR) The order of the priorities is somewhat counter-intuitive. The **higher** the priority, the **later** the event is called. For example, if it is important that your plugin has the last say in a certain event - to avoid it being changed - you should use `EventPriority.HIGHEST`. Event cancellation ------------------ [Section titled “Event cancellation”](https://docs.papermc.io/paper/dev/event-listeners/#event-cancellation) Some events can be cancelled, preventing the given action from being completed. These events implement [`Cancellable`](https://jd.papermc.io/paper/org/bukkit/event/Cancellable.html) . public class ExampleListener implements Listener { @EventHandler public void onPlayerMove(PlayerMoveEvent event) { event.setCancelled(true); }} The above example will cancel the event, meaning that the player will not be able to move. Once an event is cancelled, it will continue to call any other listeners for that event unless they add `ignoreCancelled = true` to the `@EventHandler` annotation to ignore cancelled events. public class ExampleListener implements Listener { @EventHandler(ignoreCancelled = true) public void onPlayerMove(PlayerMoveEvent event) { // ... }} Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Migrating to or from Paper | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/migration/#_top) Migrating to or from Paper ========================== It’s simple to migrate your server to or from Paper. The steps below will help you get started. Migrating to Paper ------------------ [Section titled “Migrating to Paper”](https://docs.papermc.io/paper/migration/#migrating-to-paper) ### From Vanilla [Section titled “From Vanilla”](https://docs.papermc.io/paper/migration/#from-vanilla) When migrating to Paper from Vanilla, the way worlds are stored will automatically be changed. Should you ever want to go back to Vanilla, follow the [Vanilla Migration Guide](https://docs.papermc.io/paper/migration/#to-vanilla) closely, as manual changes will be required. 1. Stop your Vanilla server if it is running, and create a full backup. 2. Download Paper from [our downloads page](https://papermc.io/downloads) and replace your Vanilla server JAR with your freshly downloaded Paper JAR. 3. Rename the downloaded file to match the name specified in the [start command](https://docs.papermc.io/paper/getting-started#running-the-server) . 4. Start your new Paper server. You have now successfully migrated to Paper. If you encounter any issues, do not hesitate to reach out for support on [our Discord server](https://discord.gg/papermc) (`#paper-help` channel). ### From Fabric/Forge [Section titled “From Fabric/Forge”](https://docs.papermc.io/paper/migration/#from-fabricforge) Because both Fabric and Forge use the Vanilla world directory structure, the same steps as the [Vanilla Migration Guide](https://docs.papermc.io/paper/migration/#from-vanilla) may be used, with one caveat. If your Fabric or Forge server used mods that added new blocks, items, or other data to the game, Paper will be unable to load these features. Additionally, note that Paper does not support Fabric or Forge mods. You will need to find plugin replacements. Any hybrids that attempt to support both mods and plugins are fundamentally flawed and not recommended for use. ### From Spigot/CraftBukkit [Section titled “From Spigot/CraftBukkit”](https://docs.papermc.io/paper/migration/#from-spigotcraftbukkit) Spigot and CraftBukkit modify the Vanilla world directory structure, making a direct migration as of `26.1` fundamentally impossible. If you wish to migrate from Spigot/CraftBukkit anyway, you will first need to **migrate from Spigot/CraftBukkit to Vanilla**, after which you can safely follow the [Vanilla Migration Guide](https://docs.papermc.io/paper/migration/#from-vanilla) . For instructions on how to do this, please refer to the Spigot documentation. Migrating from Paper -------------------- [Section titled “Migrating from Paper”](https://docs.papermc.io/paper/migration/#migrating-from-paper) ### To Vanilla [Section titled “To Vanilla”](https://docs.papermc.io/paper/migration/#to-vanilla) Because Paper shares a similar world structure to Vanilla, all you need to do is move around some files. The following list shows which files you will need to move where. **Before you move around any files, make sure your server is fully stopped**. The following files will need to be moved **from** `world/dimensions/minecraft/overworld/data/minecraft/` **into** `world/data/minecraft/`: * `game_rules.dat` * `scheduled_events.dat` * `wandering_trader.dat` * `weather.dat` * `world_gen_settings.dat` After you have moved these files, you can now replace the Paper server JAR with a Vanilla server JAR and start your Vanilla server! ### To Fabric/Forge [Section titled “To Fabric/Forge”](https://docs.papermc.io/paper/migration/#to-fabricforge) Because both Fabric and Forge use the same directory structure for world storage as Vanilla, follow the [Vanilla Migration Guide](https://docs.papermc.io/paper/migration/#to-vanilla) for this process. Note that neither Fabric nor Forge will support Paper plugins! You will be required to find replacement mods. Other Migration --------------- [Section titled “Other Migration”](https://docs.papermc.io/paper/migration/#other-migration) ### To Vanilla (pre 26.1) [Section titled “To Vanilla (pre 26.1)”](https://docs.papermc.io/paper/migration/#to-vanilla-pre-261) Because Paper stores worlds slightly differently than Vanilla, manual work is required to migrate. If these steps are not taken, your nether and end will look like they have been reset. Don’t worry! Even if this has happened, you haven’t lost any data. The Vanilla server just doesn’t know where to find it. Here is a chart to show the difference between how Vanilla and Paper store worlds. | Server Software | Overworld | Nether | End | | --- | --- | --- | --- | | Vanilla | `/world` | `/world/DIM-1` | `/world/DIM1` | | Paper | `/world` | `/world_nether/DIM-1` | `/world_the_end/DIM1` | Follow these steps to migrate from Paper to Vanilla: 1. Stop your Paper server, if it is running. 2. If you have already started your server with Vanilla, enter the `world` folder and delete both the `DIM-1` and `DIM1` folders. This step is only necessary should you have started your server with Vanilla. 3. Copy the `/world_nether/DIM-1` folder into the `/world` folder. 4. Copy the `/world_the_end/DIM1` folder into the `/world` folder. 5. Delete both the `/world_nether` and `/world_the_end` folders. 6. Replace your Paper JAR with a Vanilla server JAR. 7. Start your Vanilla server. ### To CraftBukkit or Spigot [Section titled “To CraftBukkit or Spigot”](https://docs.papermc.io/paper/migration/#to-craftbukkit-or-spigot) Paper does **not** support migration to either CraftBukkit or Spigot! While you may find success, **do not** reach out for support with issues you encounter and note that data loss is possible. Copyright © 2026 PaperMC and contributors. Built with [Starlight](https://starlight.astro.build/) . This website is not an official Minecraft website and is not associated with Mojang Studios or Microsoft. All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation or endorsement by them. --- # Paper-specific | PaperMC Docs [Skip to content](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#_top) Paper-specific ============== The arguments in this section return objects frequently used in Paper API. Block state argument -------------------- [Section titled “Block state argument”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#block-state-argument) The block state argument can be used for getting a block type and explicit, associated data. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#example-usage) public static LiteralCommandNode blockStateArgument() { return Commands.literal("blockstateargument") .then(Commands.argument("arg", ArgumentTypes.blockState()) .executes(ctx -> { final BlockState blockState = ctx.getArgument("arg", BlockState.class); ctx.getSource().getSender().sendPlainMessage("You specified a " + blockState.getType() + "!"); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#in-game-preview) Your device does not support video playback. ItemStack argument ------------------ [Section titled “ItemStack argument”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#itemstack-argument) The item stack argument is the way to retrieve an [`ItemStack`](https://jd.papermc.io/paper/org/bukkit/inventory/ItemStack.html) following the same argument format as the Vanilla `/give []` command as its second argument. The user may also define components to further customize the `ItemStack`. If you only require a [`Material`](https://jd.papermc.io/paper/org/bukkit/Material.html) , you should instead check out the [registry arguments](https://docs.papermc.io/paper/dev/command-api/arguments/registry) . ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#example-usage-1) public static LiteralCommandNode itemStackArgument() { return Commands.literal("itemstack") .then(Commands.argument("stack", ArgumentTypes.itemStack()) .executes(ctx -> { final ItemStack itemStack = ctx.getArgument("stack", ItemStack.class); if (ctx.getSource().getExecutor() instanceof Player player) { player.getInventory().addItem(itemStack); ctx.getSource().getSender().sendRichMessage("Successfully gave a ", Placeholder.component("player", player.name()), Placeholder.component("item", Component.translatable(itemStack)) ); return Command.SINGLE_SUCCESS; } ctx.getSource().getSender().sendRichMessage("This argument requires a player!"); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#in-game-preview-1) Your device does not support video playback. NamespacedKey argument ---------------------- [Section titled “NamespacedKey argument”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#namespacedkey-argument) This argument allows the user to provide any artificial (namespaced) key. The return value of this argument is a [`NamespacedKey`](https://jd.papermc.io/paper/org/bukkit/NamespacedKey.html) , which makes it useful when dealing with Bukkit API. ### Example usage [Section titled “Example usage”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#example-usage-2) public static LiteralCommandNode namespacedKeyArgument() { return Commands.literal("namespacedkey") .then(Commands.argument("key", ArgumentTypes.namespacedKey()) .executes(ctx -> { final NamespacedKey key = ctx.getArgument("key", NamespacedKey.class); ctx.getSource().getSender().sendRichMessage("You put in !", Placeholder.unparsed("key", key.toString()) ); return Command.SINGLE_SUCCESS; })) .build();} ### In-game preview [Section titled “In-game preview”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#in-game-preview-2) Your device does not support video playback. Time argument ------------- [Section titled “Time argument”](https://docs.papermc.io/paper/dev/command-api/arguments/paper/#time-argument) The time argument allows the user to define a time frame, similar to the Vanilla `/time