# Minecraft Websocket Integration

**URL:** <https://extensions.streamer.bot/t/minecraft-websocket-integration/167>\
**Category:** Approved\
**Tags:** chat, twitch, game-integration\
**Created:** [July 3, 2023, 2:08am UTC](https://extensions.streamer.bot/t/minecraft-websocket-integration/167 "2023-07-03T02:08:40Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sylvie](https://extensions.streamer.bot/user_avatar/extensions.streamer.bot/sylvie/32/531_2.png) [@Sylvie](https://extensions.streamer.bot/u/Sylvie)\
**Post date:** [July 3, 2023, 2:08am UTC](https://extensions.streamer.bot/t/minecraft-websocket-integration/167/1 "2023-07-03T02:08:40Z")

</div>

## Description

Allows websockets to run commands on your server.

### Building

```
$ mvn

```

The output plugin will be in target/

## Simple Getting Started

# Tutorial:

[![](https://extensions.streamer.bot/uploads/default/original/1X/f418f5525233e2c104fabf9f285697a51d0cf6cc.jpeg "How to Integrate Minecraft into your Livestreams!") ](https://www.youtube.com/watch?v=UHFVpDVwuIw)

## 1. Connecting to the WebSocket Server

1. Inside Streamer.bot, navigate to the `Servers/Clients` tab.
2. Click the sub-tab `Websocket Clients`.
3. Inside the window, add a new Host, by right-clicking and pressing `Add`.
4. Inside the popup window, set the `Name` to `Minecraft WebSocket Server`.
5. Inside the popup window, set the `Host` to `ws://`{localhost}`:`{8887}. (please replace `{localhost}` with your host, and `{8887}` with your port number)
6. Click `Ok`.

> You will be changing message actions later. Don’t worry!

## 2. Setting up Actions

In this guide, you will be setting up the ‘basics’ of connecting to the WebSocket server, listening to events, and sending commands.

> If this sounds like a lot, don’t worry! 99% of this is already done for you!

* * *

- [SB\_MC\_Integration\_Getting\_Started.sb](https://extensions.streamer.bot/uploads/short-url/xsDRIMDqwsRPpLlvs8aOE997G6T.sb) (8.8 KB)

1. Import the actions above.
2. Navigate to the `MC WS Message` action, you should see the following:

 ![SubActions](https://extensions.streamer.bot/uploads/default/original/1X/986932d71519826c4b0d5cbd335a80a3a3700bb3.png)

1. If you have a authentication token on the server, you need to change the %authenticationBearerToken% to the token.

![AuthBearerToken](https://extensions.streamer.bot/uploads/default/original/1X/81f3e2102485cd8868e641232a3bdf1f85615158.png)

1. Go back to the `Websocket Clients` tab, and edit the `Minecraft WebSocket Server` client. Change the `Message` to the `MC WS Message` action.

 ![WSMessage](https://extensions.streamer.bot/uploads/default/original/1X/ab24378500c975570dfb571797a4db79ce5b8c27.png)

1. Connect the websocket client to the server.

## 3. Setting up events

1. Create a new action named `MC WS Event-{event name}`.
2. Add any sub-actions you want to the action.

## 4. Sending Commands

You have 2 ways to send commands to the server.

C#:

```csharp
CPH.WebsocketSend("Command {command}");

```

Sub-Actions:

1. Define a variable named `cmd` and set it to the command you want to send.
2. Add a C# Method subaction, and call `MC WS Message Handler`, and set the method to `SendCommand`.

# Complete Getting Started

## Setting up the server

1. Create a new Minecraft server running a version of Spigot
  - currently only tested with 1.18.1

2. Put the [Plugin](https://github.com/KK964/Minecraft_Websocket_Intergration/) in the server’s plugins folder, and restart the server.
3. Set up the config file in the server’s plugins folder.

## Connecting to WebSocket Server

1. Connect to the WebSocket Server
  - If you don’t know how to do this please read [This Wiki](https://en.wikipedia.org/wiki/WebSocket)

2. Once you have connected to the WebSocket Server, you will receive a message from the Server.
3. If you receive a message from the Server, you will see one the following:
  - `Authentication not required...`
  - `Authentication needed... Send as "Bearer {Auth token}"`

4. If you received the 2nd message, you will need to authenticate with the Server.
  1. You will need to send the `Bearer` token to the Server.
  2. The Server will send back a message with the `Authentication Status`, you will see one of the following:
    - `Successfully Authenticated...`
    - `Incorrect Authentication Bearer token supplied!`

  3. If you received the 2nd message, your token that you sent was incorrect.  
Otherwise, you have successfully authenticated with the Server.

5. You will now be able to send commands to the Server.

## Sending Commands to the Server

There are a few commands that you can send to the Server.

- Minecraft commands
  - These commands are default commands that Minecraft has, and Plugin commands installed on the Server.
  - These commands are sent as `Command {Command}`
    - For example, `Command say Hello World`
      - This will send the command `say Hello World` to the Server, and will result in `Hello World` will be sent to all players.

- Event commands
- These commands allow your client to opt-in/out of events on the server
  - These commands are sent as `Listen {Event}` and `Ignore {Event}`

# Minecraft Events

## Listening

- From a connected client run `Listen <EventName>`
  - Example: `Listen PlayerDeathEvent`

## Stop Listening

- From a connected client, that is already listening to an event, run `Ignore <EventName>`
  - Example: `Ignore PlayerDeathEvent`

## List of Events, and arguments

> Events are formatted like `Event <EventName> <Json Object of arguments>`
> 
> - Example: `Event PlayerDeathEvent {"player":{"username":"KK964", "uuid":"793b1b35-18ba-419c-b735-024b63d24715"}, "message":"KK964 died of a heart attack", "location":{"world":"world", "x":-9.5, "y":67, "z":-9.5}}`

* * *

**Unchanging arguments:**

These arguments are formatted the same for all events. In event descriptions it will just be labeled as `"<key>": <Player`,`Location`,`Block`,`Entity>`

- **Player** :
  - **username** : The username of the player
  - **uuid** : The UUID of the player

- **Location** :
  - **world** : The world the event is in
  - **x** : The x coordinate of event
  - **y** : The y coordinate of event
  - **z** : The z coordinate of event

- **Block** :
  - **x** : The x coordinate of the block
  - **y** : The y coordinate of the block
  - **z** : The z coordinate of the block
  - **type** : The type of block, ex: `stone`

- **Entity** :
  - **type** : The type of entity, ex: `creeper`
  - **name** : The name of the entity
  - **location** : The location of the entity

* * *

## Player Events

> **PlayerDeathEvent**
>
> > This event is triggered when a player dies
> 
> `Event PlayerDeathEvent {"player": Player, "message": String, "location": Location}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that died
> - **message** - The death message
> - **location** - The [Location][location] of the death

> **PlayerJoinEvent**
>
> > This event is triggered when a player joins
> 
> `Event PlayerJoinEvent {"player": Player}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that joined

> **PlayerQuitEvent**
>
> > This event is triggered when a player leaves
> 
> `Event PlayerQuitEvent {"player": Player}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that left

> **PlayerChatEvent**
>
> > This event is triggered when a player chats
> 
> `Event PlayerChatEvent {"player": Player, "message": String}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that sent the message
> - **message** - The message that was sent

> **PlayerDamageEvent**
>
> > This event is triggered when a player takes damage
> 
> `Event PlayerDamageEvent {"player": Player, "damage": Number, "health": Number, "cause": String}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that took damage
> - **damage** - The amount of damage that was taken
> - **health** - The amount of health the player has left
> - **cause** - The cause of the damage [List of causes](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/entity/EntityDamageEvent.DamageCause.html)

> **PlayerHealEvent**
>
> > This event is triggered when a player regains health
> 
> `Event PlayerHealEvent {"player": Player, "regained": Number, "health": Number, "cause": String}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that was healed
> - **regained** - The amount of health that was regained
> - **health** - The amount of health the player has
> - **cause** - The cause of the regeneration [List of causes](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/entity/EntityRegainHealthEvent.RegainReason.html)

> **PlayerAdvancementDoneEvent**
>
> > This event is triggered when a player completes an advancement
> 
> `Event PlayerAdvancementDoneEvent {"player": Player, "advancement": String}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that completed the advancement
> - **advancement** - The advancement completed [List of advancements](https://minecraft.fandom.com/wiki/Advancement)

> **PlayerChangedWorldEvent**
>
> > This event is triggered when a player changes worlds
> 
> `Event Name {"player": Player, "world": String, "fromWorld": String}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that changed worlds
> - **world** - The world the player changed to
> - **fromWorld** - The world the player changed from

> **PlayerFoodChangeEvent**
>
> > This event is triggered when a players food level changes
> 
> `Event Name {"player": Player, "food": Number, "saturation": Number}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that changed food level
> - **food** - New food level
> - **saturation**? - The current saturation level, may not be returned if version is below 1.16

> **PlayerDamagePlayerEvent**
>
> > This event is triggered when a player damages another player
> 
> `Event Name {"player": Player, "damager": Player, "damage": Number, "health": Number, "damagerHealth": Number}`
> 
> Arguments:
> 
> - **player** - Player that was damaged
> - **damager** - Player that damaged the player
> - **damage** - Amount of damage that was dealt
> - **health** - The amount of health the player has left
> - **damagerHealth** - The amount of health the damager has left

> **PlayerStatusChangeEvent**
>
> > This event is triggered when one of the following changes:
> 
> - Player is swimming / no longer swimming
> - Player is flying / no longer flying
> - Player is freezing / no longer freezing
> - Player is burning / no longer burning
> - Player is gliding / no longer gliding (elytra)
> 
> `PlayerStatusChangeEvent {"player": Player, "status": Status, "oldStatus": Status}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that changed status
> - **status** - The new status
> - **oldStatus** - The old status
> 
> > - **status** - `{"isSwimming":bool,"isFreezing":bool,"isBurning":bool,"isFlying":bool,"isGliding":bool}`
> > - **isFreezing** - may not be returned if version is below 1.18

> **PlayerMoveEvent**
>
> > This event is triggered when a player moves (only when the block changes)
> 
> `PlayerMoveEvent {"player": Player, "location": Location, "fromLocation": Location, "block": Block, "standingOn": Block}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that moved
> - **location** - The [Location][location] the player moved to
> - **fromLocation** - The [Location][location] the player moved from
> - **block** - The [Block][block] the players feet are in
> - **standingOn** - The [Block][block] the player is standing on

> **PlayerExpChangeEvent**
>
> > This event is triggered when a player gains or loses experience
> 
> `Event PlayerExpChangeEvent {"player": Player, "level": Number, "oldLevel": Number, "xp": Number, "neededToLevelUp": Number}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that gained or lost experience
> - **level** - The amount of experience the player has
> - **oldLevel** - The amount of experience the player had
> - **xp** - The amount of experience points total
> - **neededToLevelUp** - The amount of experience points needed to level up

> **EventName**
>
> > This event is triggered when
> 
> `Event Name {}`
> 
> Arguments:
> 
> - \*\*\*\* -

> **PlayerKillEntityEvent**
>
> > This event is triggered when a player kills an entity
> 
> `Event PlayerKillEntityEvent {"player": Player, "entity": Entity}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that killed the entity
> - **entity** - The [Entity][entity] that was killed

* * *

## World Events

> **BlockPlaceEvent**
>
> > This event is triggered when a player places a block
> 
> `Event BlockPlaceEvent {"player": Player, "block": Block}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that placed the block
> - **block** - The [Block][block] that was placed

> **BlockBreakEvent**
>
> > This event is triggered when a player breaks a block
> 
> `Event BlockBreakEvent {"player": Player, "block": Block}`
> 
> Arguments:
> 
> - **player** - The [Player][player] that broke the block
> - **block** - The [Block][block] that was broken

# Using the Plugin in [Streamer.bot](https://streamer.bot/)

## Make sure that you have [Streamer.bot](https://streamer.bot/) installed before following guide!

* * *

## Setting up default actions

1. Inside Streamer.bot, navigate to the `Actions` tab.
2. Right click on the `Actions` tab and select `Add`.
3. Create a group for the action called `Minecraft Websocket`.
4. Name the action `MC WS Connected`.
5. Then press `Ok`.
6. Add 2 more actions to the group, called `MC WS Disconnected` and `MC WS Message`.

## Connecting to the WebSocket Server

1. Inside Streamer.bot, navigate to the `Servers/Clients` tab.
2. Click the sub-tab `Websocket Clients`.
3. Inside the window, add a new Host, by right-clicking and pressing `Add`.
4. Inside the popup window, set the `Name` to `Minecraft WebSocket Server`.
5. Inside the popup window, set the `Host` to `ws://`{localhost}`:`{8887}. (please replace `{localhost}` with your host, and `{8887}` with your port number)
6. Set the Action Connected to `MC WS Connected`.
7. Set the Action Disconnected to `MC WS Disconnected`.
8. Set the Action Message to `MC WS Message`.
9. Click `Ok`.

## Setting up Actions

In this guide, the following will be the flowchart of the actions:

**Example workflow:**

> WS Connect
> 
> - Log to file

> WS Message
> 
> - Authenticate
> - Subscribe to events
> - Send events to WS Events

> WS Disconnect
> 
> - Log to file

> WS Events
> 
> - Get event ran
> - Run WS Event-{event ran}

> WS Event-{events}
> 
> - Convert event data to Json
> - Send message in twitch chat

### 1. MC WS Connected

1. Make a sub action `File` → `Write to file`, make a new file called `WS_Logs.txt`, and set it to append to the file, with the text `%date% %time% - WS Connected`.

### 2. MC WS Disconnected

1. Make a sub action `File` → `Write to file`, select the file called `WS_Logs.txt`, and set it to append to the file, with the text `%date% %time% - WS Disconnected`.

### 3. MC WS Message

This is where the magic starts!

1. Make a sub action `File` → `Write to file`, select the file called `WS_Logs.txt`, and set it to append to the file, with the text `%date% %time% - WS Message: %message%`.
2. Make a sub action `C#` → `Run C# code`
  - inside the C# window, add the following inside `Execute()`:

```csharp
string auth = ""; // Add your authentication token here
string[] listeners = { // Add the events you want to listen to here
  "PlayerDeathEvent",
};

string msg = args["message"].ToString();

if (msg.StartsWith("Authentication needed")) {
  // Send authentication message
  // Set connection to the 0-based index of your Minecraft websocket client.
  CPH.WebsocketSend("Bearer " + auth, connection: 0);
  return true;
}
if (msg.StartsWith("Authentication not required") || msg.StartsWith("Successfully Authenticated")) {
  // Subscribe to events
  string listenString = "Listen " + String.Join("\nListen ", listeners);

  // Set connection to the 0-based index of your Minecraft websocket client.
  CPH.WebsocketSend(listenString, connection: 0);
  return true;
}

if (msg.StartsWith("Event ")) {
  // Event received
  CPH.SetArgument("event", msg.Substring("Event ".Length));
  CPH.RunAction("MC WS Event Handler");
}
return true;

```

1. This will handle all messages between the server and the client.

### MC WS Event Handler

1. Make a sub action `C#` → `Run C# code`
  - inside the C# window, add the following inside `Execute()`:

```csharp
string ev = args["event"].ToString();
string evRun = ev.Split(' ')[0];
string unParsedJson = ev.Substring(evRun.Length);
CPH.SetArgument("event-json", unParsedJson);
CPH.RunAction("MC WS Event-" + evRun);
return true;

```

1. This will forward the event to the correct action.

### MC WS Event-{event ran}

1. Replace `{event ran}` with the event name you want to handle.
2. Handle the event
3. Example with PlayerDeathEvent: (making the action name `MC WS Event-PlayerDeathEvent`)

```csharp
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;

public class CPHInline
{

  public class Player
  {
    public string username { get; set; }
    public string uuid { get; set; }
  }

  public class Location
  {
    public string world { get; set; }
    public double x { get; set; }
    public double y { get; set; }
    public double z { get; set; }
  }

  public class Death
  {
    public Player player { get; set; }
    public string message { get; set; }
    public Location location { get; set; }
  }

  public bool Execute()
  {
    Death death = JsonConvert.DeserializeObject<Death>(args["event-json"].ToString());
    Player player = death.player;
    Location location = death.location;
    CPH.SendMessage(death.message);
    CPH.SendMessage(player.username + " died in " + location.world + ", at " + location.x + ", " + location.y + ", " + location.z);
    return true;
  }
}

```

## Forwarding Twitch Chat to Minecraft Chat

1. Inside Streamer.bot, navigate to the `Actions` tab.
2. Make an action called `Forward Twitch Chat to Minecraft Chat`.
3. Navigate to the `Settings` → `Events` tab.
4. Set `Chat Message` to `Forward Twitch Chat to Minecraft Chat`.
5. Go back to the `Forward Twitch Chat to Minecraft Chat` action.
6. Make a sub action `C#` → `Run C# code`
  - inside the C# window, add the following inside `Execute()`:

```csharp
string msg = args["message"].ToString();
// Make sure to remove bad characters from the message, if you don't, users can break out of tellraw, and other commands
msg = msg.Replace("\\", "");
msg = msg.Replace("\"", "");

string user = args["user"].ToString();

// Set connection to the 0-based index of your Minecraft websocket client.
CPH.WebsocketSend("Command say ["+user+"] " + msg, connection: 0);
return true;

```

1. This will forward the message to the Minecraft server.
