Skip to content

Commit

Permalink
feat: more javadoc links
Browse files Browse the repository at this point in the history
  • Loading branch information
zlataovce committed May 3, 2024
1 parent 65963eb commit 05aa7c3
Show file tree
Hide file tree
Showing 15 changed files with 114 additions and 84 deletions.
22 changes: 14 additions & 8 deletions docs/paper/contributing/events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,29 @@ All new events should go in the package (sub-package of) `io.papermc.paper.event

### Constructors

All new constructors added should be annotated with `@ApiStatus.Internal` to signify that they are not considered
API and can change at any time without warning.
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` and `@DoNotUse`.
Constructors that are being replaced, if they aren't being removed, should be marked with
<Javadoc name={"java.lang.Deprecated"} project={"java"}>`@Deprecated`</Javadoc> and
<Javadoc name={"io.papermc.paper.annotation.DoNotUse"}>`@DoNotUse`</Javadoc>.

### Mutability
Certain API types are "mutable" which can lead to unexpected behavior within events. Mutable types like
`Location` and `Vector` should therefore be cloned when returned from a "getter" in an event.
<Javadoc name={"org.bukkit.Location"}>`Location`</Javadoc> and <Javadoc name={"org.bukkit.util.Vector"}>`Vector`</Javadoc>
should therefore be cloned when returned from a "getter" in an event.

### `HandlerList`
For an event class or any subclass of it to be listened to, a `HandlerList` field must be present with an instance and static method
to retrieve it. See the docs for <Javadoc name={"org.bukkit.event.Event"}>`Event`</Javadoc> for specifics. This field should be static and
final and named `HANDLER_LIST`.
For an event class or any subclass of it to be listened to, a <Javadoc name={"org.bukkit.event.HandlerList"}>`HandlerList`</Javadoc>
field must be present with an instance and static method to retrieve it.
See the docs for <Javadoc name={"org.bukkit.event.Event"}>`Event`</Javadoc> 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

* New parameters or method returns of type `ItemStack` should be `@NotNull`.
* New parameters or method returns of type <Javadoc name={"org.bukkit.inventory.ItemStack"}>`ItemStack`</Javadoc>
should be [`@NotNull`](https://javadoc.io/doc/org.jetbrains/annotations/latest/org/jetbrains/annotations/NotNull.html).
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ All `CommandSender`s are single audiences. This includes players, the console, a
`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 methods are available on `CommandSender`, `Server`, `Team` and `World`.
This means that all the [`Audience`](https://jd.advntr.dev/api/latest/net/kyori/adventure/audience/Audience.html)
methods are available on <Javadoc name={"org.bukkit.command.CommandSender"}>`CommandSender`</Javadoc>,
<Javadoc name={"org.bukkit.Server"}>`Server`</Javadoc>, <Javadoc name={"org.bukkit.scoreboard.Team"}>`Team`</Javadoc>
and <Javadoc name={"org.bukkit.World"}>`World`</Javadoc>.

## `ForwardingAudience`

The `ForwardingAudience` wraps a collection of `Audience` instances and forwards messages to all of them. This is useful
for sending messages to multiple audiences (players) at once.
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.

```java
// Server is a ForwardingAudience which includes all online players and the console
Expand All @@ -33,8 +37,8 @@ Audience audience = Audience.audience(Audience...);
## What do `Audience`s 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` to a player
using `Audience#sendMessage(Component)`.
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,30 @@ Adventure's Javadocs for all-things translations can be found [here](https://jd.

## GlobalTranslator

All translation is done through the [GlobalTranslator](https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/GlobalTranslator.html). You can render translations yourself and add new sources
for translations.
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 [TranslationRegistry](https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/TranslationRegistry.html) or implementing
the [Translator](https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/Translator.html) interface yourself.
You can add sources to the `GlobalTranslator` by creating instances of [`TranslationRegistry`](https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/TranslationRegistry.html)
or implementing the [`Translator`](https://jd.advntr.dev/api/latest/net/kyori/adventure/translation/Translator.html) interface yourself.

## 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 `Component` API exists, except for ItemStack display text like the display name or lore. So
chat, entity display names, scoreboards, tab lists, etc., all support translations.
in a resource pack, server-side translations are the only alternative. They work anywhere the component API exists, except for <Javadoc name={"org.bukkit.inventory.ItemStack"}>`ItemStack`</Javadoc>
display text like the display name or lore. So chat, entity display names, scoreboards, tab lists, etc., all support translations.

:::caution

The player's language as declared in the settings packet sent by the client arrives **after** the player has joined the server, so there are no guarantees that
translations will work for a client that is joining during the `PlayerJoinEvent` or any earlier event. You can listen for the first `PlayerClientOptionsChangeEvent` after
joining to know with 100% certainty what language the client that joined is using.
translations will work for a client that is joining during the <Javadoc name={"org.bukkit.event.player.PlayerJoinEvent"}>`PlayerJoinEvent`</Javadoc> or any earlier event.
You can listen for the first <Javadoc name={"com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent"}>`PlayerClientOptionsChangeEvent`</Javadoc>
after joining to know with 100% certainty what language the client that joined is using.

:::

## Examples

### ResourceBundle
### `ResourceBundle`
```properties title="src/main/resources/your/plugin/Bundle_en_US.properties"
some.translation.key=Translated Message: {0}
```
Expand All @@ -51,9 +52,10 @@ registry.registerAll(Locale.US, bundle, true);
GlobalTranslator.translator().addSource(registry);
```

This creates a new `TranslationRegistry` under a specified namespace. Then a `ResourceBundle` is created from a bundle located on the classpath with
the specified `Locale`. Finally, that `ResourceBundle` is added to the registry. That registry is then added as a source to the `GlobalTranslator`. This
makes all the translations available server-side.
This creates a new `TranslationRegistry` under a specified namespace. Then, a <Javadoc name={"java.util.ResourceBundle"} project={"java"}>`ResourceBundle`</Javadoc>
is created from a bundle located on the classpath with the specified <Javadoc name={"java.util.Locale"} project={"java"}>`Locale`</Javadoc>.
Finally, that `ResourceBundle` is added to the registry. That registry is then added as a source to the `GlobalTranslator`.
This makes all the translations available server-side.

Now you can use translation keys in translatable components.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ signal that a better alternative in components is available and should be migrat

:::

## Creating Components
## Creating components

Components can be interacted with as objects. There are different interfaces for each type along with
builders for all the types. These objects are immutable so when constructing more complex components, it's
Expand Down Expand Up @@ -76,7 +76,7 @@ For complete documentation on the Adventure Component API Paper and Velocity use

## MiniMessage

Paper and Velocity include the MiniMessage library which is a string representation of components. If you prefer working with
Paper and Velocity include the MiniMessage library, which is a string representation of components. If you prefer working with
strings rather than objects, MiniMessage is vastly superior to the legacy string format. It can utilize the tree
structure for style inheritance and can represent the more complex component types while legacy cannot.

Expand All @@ -102,7 +102,7 @@ MiniMessage has a [web viewer](https://webui.advntr.dev/), which is useful for c

:::

## JSON Format
## JSON format

Components can be serialized and deserialized from a standard JSON format. This format is used
in Vanilla in various commands which accept component arguments like `/tellraw`. Below is a simple example
Expand Down Expand Up @@ -142,37 +142,40 @@ There are online tools to make generating this format much easier like [JSON Tex

## Serializers

Paper and Velocity come bundled with different serializers for converting between `Component`s and other forms
of serialized text.
Paper and Velocity come bundled with different serializers for converting between
[`Component`](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/Component.html)s and other forms of serialized text.

### [GsonComponentSerializer](https://jd.advntr.dev/text-serializer-gson/latest)
### [`GsonComponentSerializer`](https://jd.advntr.dev/text-serializer-gson/latest)

Converts between `Component` and JSON-formatted strings with convenience methods to directly deal with Gson's `JsonElement`.
This conversion is lossless and is the preferred form of serialization
for components that do not have to be edited by users regularly.
Converts between `Component`
and JSON-formatted strings with convenience methods to directly deal with Gson's
[`JsonElement`](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/JsonElement.html).
This conversion is lossless and is the preferred form of serialization for components that do not have to be edited by users regularly.

### [MiniMessage](https://jd.advntr.dev/text-minimessage/latest)
### [`MiniMessage`](https://jd.advntr.dev/text-minimessage/latest)

Converts between `Component` and a MiniMessage-formatted string. This conversion is lossless and is the preferred form of
Converts between `Component`
and a MiniMessage-formatted string. This conversion is lossless and is the preferred form of
serialization for components that have to be edited by users. There is also extensive customization you can add to the
serializer, which is [documented here](https://docs.advntr.dev/minimessage/api.html#getting-started).

### [PlainTextComponentSerializer](https://jd.advntr.dev/text-serializer-plain/latest)
### [`PlainTextComponentSerializer`](https://jd.advntr.dev/text-serializer-plain/latest)

Serializes a `Component` into a plain text string. This is very lossy as all style information as well as most other
types of components will lose information. There may be special handling for `TranslatableComponent`s to be serialized
types of components will lose information. There may be special handling for
[`TranslatableComponent`](https://jd.advntr.dev/api/latest/net/kyori/adventure/text/TranslatableComponent.html)s to be serialized
into a default language, but generally this shouldn't be used except in certain circumstances, like logging to a text file.

### [LegacyComponentSerializer](https://jd.advntr.dev/text-serializer-legacy/latest)
### [`LegacyComponentSerializer`](https://jd.advntr.dev/text-serializer-legacy/latest)

:::caution

This is not recommended for use as the legacy format may be removed in the future.

:::

Converts between `Component` and the legacy string format. This conversion is very lossy as component types and events
do not have a legacy string representation.
Converts between `Component` and the legacy string format.
This conversion is very lossy as component types and events do not have a legacy string representation.

A more useful use case is converting legacy text to MiniMessage format in a migration process.
```java
Expand All @@ -187,7 +190,8 @@ final String miniMessageString = MiniMessage.miniMessage().serialize(
:::note

There are 2 built-in legacy serializers, one dealing with `§` symbols and the other for
`&` symbols. They have their own instances available through `LegacyComponentSerializer#legacySection()`
and `LegacyComponentSerializer#legacyAmpersand()`.
`&` symbols. They have their own instances available through
[`LegacyComponentSerializer#legacySection()`](https://jd.advntr.dev/text-serializer-legacy/latest/net/kyori/adventure/text/serializer/legacy/LegacyComponentSerializer.html#legacySection())
and [`LegacyComponentSerializer#legacyAmpersand()`](https://jd.advntr.dev/text-serializer-legacy/latest/net/kyori/adventure/text/serializer/legacy/LegacyComponentSerializer.html#legacyAmpersand()).

:::
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ Custom `InventoryHolder`s have no such downsides and by using them you're guaran

## Creating a custom holder

The first step is to implement the `InventoryHolder` interface.
We can do this the following way: create a new class that will create our `Inventory` in the constructor.
The first step is to implement the <Javadoc name={"org.bukkit.inventory.InventoryHolder"}>`InventoryHolder`</Javadoc> interface.
We can do this the following way: create a new class that will create our <Javadoc name={"org.bukkit.inventory.Inventory"}>`Inventory`</Javadoc> in the constructor.

:::info

The constructor takes your main plugin class as an argument in order to create the `Inventory`.
If you wish, you can use the static method `Bukkit#createInventory(InventoryHolder, int)` instead and remove the argument.
If you wish, you can use the static method <Javadoc name={"org.bukkit.Bukkit#createInventory(org.bukkit.inventory.InventoryHolder,int)"}>`Bukkit#createInventory(InventoryHolder, int)`</Javadoc> instead and remove the argument.

:::

Expand Down Expand Up @@ -68,8 +68,8 @@ player.openInventory(myInventory.getInventory());

## Listening to an event

Once we have the inventory open, we can listen to any inventory events we like and check if the `Inventory#getHolder()`
returns an instance of our `MyInventory`.
Once we have the inventory open, we can listen to any inventory events we like and check if
<Javadoc name={"org.bukkit.inventory.Inventory#getHolder()"}>`Inventory#getHolder()`</Javadoc> returns an instance of our `MyInventory`.

```java
@EventHandler
Expand Down
2 changes: 1 addition & 1 deletion docs/paper/dev/api/event-api/chat-event.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Let's say we want to render our chat to look like this:

![](./assets/plain-message-rendering.png)

To do this, we need to return a new `Component` that contains the message we want to send.
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.

```java title="ChatListener.java"
public class ChatListener implements Listener, ChatRenderer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ This will allow other plugins to listen to your custom events and add functional

## Creating a custom event

To create a custom event, you need to create a class that extends `Event`.
Each event requires a `HandlerList` that will contain all the listeners that are listening to that event.
To create a custom event, you need to create a class that extends <Javadoc name={"org.bukkit.event.Event"}>`Event`</Javadoc>.
Each event requires a <Javadoc name={"org.bukkit.event.HandlerList"}>`HandlerList`</Javadoc> 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 the BlockPistonEvent, which cannot be listened to directly.
An example of this is <Javadoc name={"org.bukkit.event.block.BlockPistonEvent"}>`BlockPistonEvent`</Javadoc>, which cannot be listened to directly.

This list is used to call the listeners when the event is called.

Expand Down Expand Up @@ -134,8 +134,9 @@ public class ExamplePlugin extends JavaPlugin {
}
```

When an event is cancellable, `Event#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` manually.
When an event is cancellable, <Javadoc name={"org.bukkit.event.Event#callEvent()"}>`Event#callEvent()`</Javadoc>
will return false if the event was cancelled. This allows you to directly use `callEvent` in your `if` statement,
instead of having to check <Javadoc name={"org.bukkit.event.Cancellable#isCancelled()"}>`Cancellable#isCancelled()`</Javadoc> manually.

```java title="ExamplePlugin.java"
public class ExamplePlugin extends JavaPlugin {
Expand Down
Loading

0 comments on commit 05aa7c3

Please sign in to comment.