Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event API documentation #87

Merged
merged 4 commits into from
Oct 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions config/sidebar.paper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,33 @@ const paper: SidebarsConfig = {
id: "dev/README",
},
items: [
"dev/getting-started/project-setup",
"dev/getting-started/plugin-yml",
{
type: "category",
label: "Getting started",
collapsed: true,
link: {
type: "doc",
id: "dev/getting-started/README",
},
items: [
"dev/getting-started/project-setup",
"dev/getting-started/plugin-yml",
],
},
{
type: "category",
label: "Event API",
collapsed: true,
link: {
type: "doc",
id: "dev/event-api/README",
},
items: [
"dev/event-api/event-listeners",
"dev/event-api/handler-lists",
"dev/event-api/custom-events",
],
},
],
},
],
Expand Down
11 changes: 11 additions & 0 deletions docs/paper/dev/event-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import DocCardList from "@theme/DocCardList";
import { useCurrentSidebarCategory } from "@docusaurus/theme-common";

# Paper Event API

Welcome to the Paper Event API Guide!
This guide includes information for developers to use events inside Paper plugins.

---

<DocCardList items={useCurrentSidebarCategory().items} />
131 changes: 131 additions & 0 deletions docs/paper/dev/event-api/custom-events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
slug: /dev/custom-events
---

# Custom Events

Creating custom events is a great way to add functionality to your plugin.
This will allow for other people to listen for your custom events and add functionality to your plugin.

## Creating a custom event

To create a custom event, you need to create a class that extends `Event`. Each event has a `HandlerList` that contains all the listeners that are listening for that event.

This list is used to call the listeners when the event is called.
olijeffers0n marked this conversation as resolved.
Show resolved Hide resolved

olijeffers0n marked this conversation as resolved.
Show resolved Hide resolved
:::info `getHandlerList`

Although it is not inherited from `Event`, you need to add a static `getHandlerList()` method and return the `HandlerList` for your event.
Both methods are required for your event to work.

:::

```java title="PaperIsCoolEvent.java"
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;
}
olijeffers0n marked this conversation as resolved.
Show resolved Hide resolved
}
```

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.

```java title="PaperIsCoolEvent.java"
public class PaperIsCoolEvent extends Event {

private static final HandlerList HANDLER_LIST = new HandlerList();
private Component message;

public PaperIsCoolEvent(Component message) {
this.message = message;
}

public static HandlerList getHandlerList() {
return HANDLER_LIST;
}

@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}

public Component getMessage() {
return this.message;
}

public void setMessage(Component message) {
this.message = message;
}
}
```

## Calling the event

Now that we have created our event, we can call it.

```java title="ExamplePlugin.java"
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

If you want to allow your event to be cancelled, you can implement the `Cancellable` interface.

```java title="PaperIsCoolEvent.java"
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.

```java title="ExamplePlugin.java"
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());
}
}
}
```
134 changes: 134 additions & 0 deletions docs/paper/dev/event-api/event-listeners.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
slug: /dev/event-listeners
---

# Event 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

To listen for events, you need to create a class that implements `Listener`.
This class can be called anything you want, but it is recommended to name it something related to the events you are listening for.

```java title="ExampleListener.java"
public class ExampleListener implements Listener {
// ...
}
```

## `@EventHandler`

To listen for an event, you need to create a method that is annotated with `@EventHandler`.
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

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 for.

```java title="ExampleListener.java"
public class ExampleListener implements Listener {

@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
// ...
}
}
```

:::note Events

There is no list of events that can be listened for, however take a look
[here](https://jd.papermc.io/paper/1.19/org/bukkit/event/Event.html) to see all events that extend `Event`.

:::

## 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.

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

@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(new ExampleListener(), this);
}
}
```

## Event priority

You can also specify the priority of the event.

```java title="ExampleListener.java"
public class ExampleListener implements Listener {

@EventHandler(priority = EventPriority.HIGH)
public void onPlayerJoin(PlayerJoinEvent event) {
// ...
}
}
```
There are six different priorities that you can use:
- `EventPriority.LOWEST`
- `EventPriority.LOW`
- `EventPriority.NORMAL`
- `EventPriority.HIGH`
- `EventPriority.HIGHEST`
- `EventPriority.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`.

:::note

The `MONITOR` priority is used to monitor the event, but not change it. It is called after all other priorities have been called.
This means you can get the result of any plugin interaction such as cancellation or modification.

:::

## Event cancellation

Some events can be cancelled, preventing the given action from being completed. These events implement `Cancellable`.

```java title="ExampleListener.java"
public class ExampleListener implements Listener {

@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.setCancelled(true);
}
}
```

:::warning

It is important to consider that another plugin could have cancelled or changed the event before your plugin is called.
Always check the event before doing anything with it.

:::

The above example will cancel the event, meaning that the player will not be able to join the server.
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.

```java title="ExampleListener.java"
public class ExampleListener implements Listener {

@EventHandler(ignoreCancelled = true)
public void onPlayerJoin(PlayerJoinEvent event) {
// ...
}
}
```


59 changes: 59 additions & 0 deletions docs/paper/dev/event-api/handler-lists.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
slug: /dev/handler-lists
---

# Handler Lists

Every `Event` has a `HandlerList` that contains all the listeners that are listening for that event.
This list is used to call the listeners when the event is called.

## Getting the handler list for an event

To get the handler list for an event, you can call `getHandlerList()` on the specific event class.

```java title="ExampleListener.java"
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

To unregister a listener, you can call `unregister()` on the `HandlerList` that the listener is registered to.

```java title="ExampleListener.java"
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` or `Plugin` for more convenience.
Likewise, you can also unregister all listeners for a specific event by calling `unregisterAll()` on the `HandlerList`.
11 changes: 11 additions & 0 deletions docs/paper/dev/getting-started/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import DocCardList from "@theme/DocCardList";
import { useCurrentSidebarCategory } from "@docusaurus/theme-common";

# Development Guide

Welcome to the Paper Development Guide! This guide includes information and tutorials for
how to start developing plugins for Paper.

---

<DocCardList items={useCurrentSidebarCategory().items} />