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

set event result, and add warnings to velocity plugin messaging docs #479

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
99 changes: 91 additions & 8 deletions docs/velocity/dev/api/plugin-messaging.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ flowchart LR
backend -->|"3 (Incoming)"| Velocity -->|"4 (Outgoing)"| player
```

:::warning

When listening to `PluginMessageEvent`, ensure the result is
<Javadoc name={"com/velocitypowered/api/event/connection/PluginMessageEvent$ForwardResult#handled()"} project={"velocity"}>`ForwardResult.handled()`</Javadoc>
if you do not intend the client to participate.

If the result is forwarded, players can impersonate the proxy to your backend servers.

Additionally, ensure the result is set correctly after actually handling correct messages, to prevent them from being leaked to the other party.

This can be achieved with unconditionally setting the result between checking the identifier and checking the source, as shown in the examples.

:::

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
Expand All @@ -26,6 +40,19 @@ 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.

```mermaid
flowchart LR
subgraph handle from player
direction LR
a[player] --> b[Velocity] ~~~ c[backend]
end
subgraph forward from player
direction LR
d[player] --> e[Velocity] --> f[backend]
end
```


```java
public static final MinecraftChannelIdentifier IDENTIFIER = MinecraftChannelIdentifier.from("custom:main");

Expand All @@ -36,12 +63,23 @@ public void onProxyInitialization(ProxyInitializeEvent event) {

@Subscribe
public void onPluginMessageFromPlayer(PluginMessageEvent event) {
if (!(event.getSource() instanceof Player)) {
// Check if the identifier matches first, no matter the source.
if (!IDENTIFIER.equals(event.getIdentifier())) {
return;
}
Player player = (Player) event.getSource();
// Ensure the identifier is what you expect before trying to handle the data
if (event.getIdentifier() != IDENTIFIER) {

// 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;
}

Expand All @@ -64,6 +102,15 @@ Otherwise, a player can pretend to be your proxy, and spoof them.

:::

```mermaid
flowchart LR
subgraph Send to Backend
direction LR
player ~~~ Velocity --> backend
end
```


### Using any connected player

This is useful if you just want to communicate something relevant to the entire server,
Expand Down Expand Up @@ -104,6 +151,18 @@ for the event to be fired.

An example use case could be handing a request to transfer the player to another server.

```mermaid
flowchart LR
subgraph handle from backend
direction RL
a[backend] --> b[Velocity] ~~~ c[ player]
end
subgraph forward from backend
direction RL
d[backend] --> e[Velocity] --> f[player]
end
```

```java
public static final MinecraftChannelIdentifier IDENTIFIER = MinecraftChannelIdentifier.from("custom:main");

Expand All @@ -114,12 +173,28 @@ public void onProxyInitialization(ProxyInitializeEvent event) {

@Subscribe
public void onPluginMessageFromBackend(PluginMessageEvent event) {
if (!(event.getSource() instanceof ServerConnection)) {
// 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;
}
ServerConnection backend = (ServerConnection) event.getSource();
// Ensure the identifier is what you expect before trying to handle the data
if (event.getIdentifier() != IDENTIFIER) {

// 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;
}

Expand All @@ -138,6 +213,14 @@ This is only really useful for when you are making client-side mods. Otherwise,

:::

```mermaid
flowchart RL
subgraph Send to Player
direction RL
backend ~~~ Velocity --> player
end
```

```java
public boolean sendPluginMessageToPlayer(Player player, ChannelIdentifier identifier, byte[] data) {
// On success, returns true
Expand Down