> For the complete documentation index, see [llms.txt](https://esmp-fun.gitbook.io/plugins/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://esmp-fun.gitbook.io/plugins/community-chat/reference/relay-settings.md).

# Relay settings

**What's the relay?** It's the hub of your network — one program (`ccsrv-relay.jar`) that all the Minecraft servers and Discords connect to. Think of it as the room everyone talks in. Exactly **one person** — the network operator — runs it, on one machine. It is *not* a Minecraft plugin: it runs on its own with plain Java, no Minecraft server needed.

**This page is for the network operator only.** If you just want to connect your Minecraft server to an existing network, you never touch any of this — you want the [spoke settings](/plugins/community-chat/reference/spoke-settings.md) instead.

{% hint style="danger" %}
Never share your `ccsrv-relay.jar` with anyone. Your copy is personal to your purchase; community admins only ever need `ccsrv-spoke.jar` and the token you give them. A relay jar that gets passed around will eventually get your licence revoked.
{% endhint %}

This page walks through the complete relay `config.yml`, section by section. You only ever *need* the bot token and the `communities:` blocks — the [setup guide](/plugins/community-chat/getting-started/set-up-the-network.md) covers those. Everything else is optional tuning; if a key is missing from your file, the default shown here is used.

{% hint style="info" %}
**Location:** next to `ccsrv-relay.jar` (the relay creates a template for you on first start).

After changing the file, restart the relay — it takes a few seconds and the servers reconnect by themselves.
{% endhint %}

***

## Listen

Where the relay accepts connections from the Minecraft servers.

```yaml
listen:
  host: 0.0.0.0
  port: 8377
```

<details>

<summary><code>host</code></summary>

**Default:** `0.0.0.0` (listen on every network interface)

Leave this alone unless you know you need otherwise. `0.0.0.0` means "accept connections from anywhere", which is what you want — the spokes connect in over the internet.

</details>

<details>

<summary><code>port</code></summary>

**Default:** `8377`

The one port the Minecraft servers connect to. It must be reachable from the internet — the [hosting guides](/plugins/community-chat/getting-started/relay-on-a-minecraft-server.md) show where to open it. On Minecraft hosting, set this to the port your panel assigned you (you can't pick the number there — the relay adapts, not the host). If you change it, every community's `relay.url` changes with it (`ws://your-address:PORT`).

</details>

***

## Discord

The bot connection and how Minecraft chat looks on Discord.

```yaml
discord:
  token: "YOUR_BOT_TOKEN"
  style: webhook
  avatarUrlTemplate: "https://mc-heads.net/avatar/%uuid%"
  truncateLength: 256
  batchFlushMs: 1200
```

<details>

<summary><code>token</code></summary>

Your bot's token from [discord.com/developers/applications](https://discord.com/developers/applications) (Bot page). Treat it like a password.

{% hint style="warning" %}
On that same Bot page, the **Message Content Intent** toggle must be ON — without it the bot can't read anything and the bridge stays silent.
{% endhint %}

</details>

<details>

<summary><code>style</code></summary>

**Options:** `webhook` or `bot` — **Default:** `webhook`

How Minecraft messages appear on Discord:

* `webhook` — each player shows up with their own name and their Minecraft head as avatar. Prettiest, pick this.
* `bot` — the bot posts everything as itself, with the server tag written in the text. Use only if webhooks are blocked on your server.

</details>

<details>

<summary><code>avatarUrlTemplate</code></summary>

**Default:** `https://mc-heads.net/avatar/%uuid%`

Where the player-head avatars come from (used with `style: webhook`). `%uuid%` is replaced with the player's Minecraft UUID automatically. Only change this if you prefer a different head-rendering service.

</details>

<details>

<summary><code>truncateLength</code></summary>

**Default:** `256`

Discord messages longer than this many characters get shortened with `…` before they reach Minecraft chat. Keeps someone's essay on Discord from flooding everyone's screen in-game.

</details>

<details>

<summary><code>batchFlushMs</code></summary>

**Default:** `1200` (milliseconds)

Chat heading to Discord is grouped into small bundles so Discord's rate limits never become a problem. 1200 is a good value — leave it.

</details>

***

## Network

The network's identity and anti-spam basics.

```yaml
network:
  name: "CrossCommunity"
  throttle:
    messages: 5
    perSeconds: 10
  eventsToSpokes: [death, advancement]
```

<details>

<summary><code>name</code></summary>

**Default:** `CrossCommunity`

Your network's name. Shown when several people's messages get bundled into one Discord post, and in system notices.

</details>

<details>

<summary><code>throttle</code></summary>

**Default:** `5` messages per `10` seconds

Anti-spam: how many messages one player may send to the network within the given window. Messages over the limit still appear on the player's own server — they just don't cross to the others, so nobody can flood the whole network.

</details>

<details>

<summary><code>eventsToSpokes</code></summary>

**Options:** any of `join`, `quit`, `death`, `advancement` — **Default:** `[death, advancement]`

Which events also show up **in-game** on the other servers. Discord always gets all events — this only controls in-game chat. Joins/quits are off by default because five servers' worth of joins gets spammy fast.

</details>

***

## General

A few top-level settings.

```yaml
logTraffic: false
dbPath: "ccsrv.db"
staffLogChannelId: 0
```

<details>

<summary><code>logTraffic</code></summary>

**Default:** `false`

When `true`, the relay prints one console line for every message that crosses the network. Handy while setting up ("is my message arriving?"), noisy afterwards — turn it back off.

</details>

<details>

<summary><code>dbPath</code></summary>

**Default:** `ccsrv.db`

The file where account links, punishments and the staff action log live. It's created automatically next to the jar. Include it in your backups.

</details>

<details>

<summary><code>staffLogChannelId</code></summary>

**Default:** `0` (off)

Optional: one Discord channel (e.g. in a private staff Discord) that receives a copy of **every** community's punishment log. See [Moderation](/plugins/community-chat/using-it/moderation.md).

</details>

***

## Automod

Automatic moderation. Every message crossing the network passes these checks — in-game and Discord alike. The defaults are sensible; details in [Moderation](/plugins/community-chat/using-it/moderation.md).

```yaml
automod:
  wordPacks:
    - action: censor
      words: []
    - action: drop
      words: []
    - action: mute
      words: []
  linkPolicy: strip
  allowDomains: [youtube.com, imgur.com, discord.gg]
  capsMinLength: 12
  capsPercent: 80
  repeatWindowSeconds: 15
  escalationHits: 3
  escalationWindowMinutes: 10
  escalationMuteMinutes: 30
```

<details>

<summary><code>wordPacks</code></summary>

Word lists, from mild to severe. Put words in the list whose punishment fits:

* `censor` — the word is replaced with `****` and the message still goes through.
* `drop` — the message is quietly not delivered to the network.
* `mute` — the message is blocked AND the sender is instantly muted.

Matching is case-insensitive and catches common letter-swaps.

{% hint style="success" %}
**You usually never touch this YAML.** On first start the relay creates three plain text files next to the config — `words-censor.txt`, `words-drop.txt`, `words-mute.txt` — one word or phrase per line. Fill those instead with any text editor; they're re-read when someone presses **Save** in the in-game menu or when the relay restarts. Both sources are combined, so the YAML lists here are only for people who prefer keeping everything in one file.
{% endhint %}

</details>

<details>

<summary><code>linkPolicy</code> and <code>allowDomains</code></summary>

**Options:** `allow`, `strip`, `block` — **Default:** `strip`

What to do with links in chat:

* `allow` — links pass through untouched.
* `strip` — links are replaced with `[link removed]`, unless the site is in `allowDomains`.
* `block` — messages containing non-allowed links are not delivered at all.

`allowDomains` lists the sites that are always fine (subdomains included).

</details>

<details>

<summary><code>capsMinLength</code> and <code>capsPercent</code></summary>

**Defaults:** `12` and `80`

SHOUTING control: messages at least `capsMinLength` characters long that are at least `capsPercent`% uppercase simply get lowercased. Nobody is punished — the message just arrives calm.

</details>

<details>

<summary><code>repeatWindowSeconds</code></summary>

**Default:** `15`

Sending the exact same message twice within this many seconds = the copy is dropped.

</details>

<details>

<summary><code>escalationHits</code>, <code>escalationWindowMinutes</code>, <code>escalationMuteMinutes</code></summary>

**Defaults:** `3` hits / `10` minutes / `30` minutes

Escalation for repeat offenders: if someone triggers a `drop` (word filter or link policy) `escalationHits` times within `escalationWindowMinutes`, they are automatically muted for `escalationMuteMinutes`.

</details>

***

## Filters (advanced)

```yaml
filters: []
```

<details>

<summary><code>filters</code></summary>

**Default:** `[]` (none)

Extra fine-grained filters using regular expressions, for advanced users. They run BEFORE automod. Most networks leave this empty — the automod section covers normal needs.

</details>

***

## Communities

The heart of the config: one block per community. Copy-paste a block to add another. The block name (`emerald`, `sapphire`, …) is internal — pick anything without spaces; players only ever see the `tag`.

```yaml
communities:
  emerald:
    displayName: "EmeraldMC"
    tag: "EMER"
    color: "#4caf50"
    spokeToken: "CHANGE-ME-LONG-RANDOM-1"
    guildId: 111111111111111111
    chatChannelId: 222222222222222222
    eventsChannelId: 0
    linkedRoleId: 0
    modLogChannelId: 0
    staffChannelId: 0
  sapphire:
    displayName: "SapphireSMP"
    tag: "SAPH"
    color: "#2196f3"
    spokeToken: "CHANGE-ME-LONG-RANDOM-2"
    guildId: 333333333333333333
    chatChannelId: 444444444444444444
    eventsChannelId: 0
    linkedRoleId: 0
    modLogChannelId: 0
    staffChannelId: 0
```

<details>

<summary><code>displayName</code></summary>

The community's full name. Shown when a player hovers over the tag in-game.

</details>

<details>

<summary><code>tag</code></summary>

The short tag players see in front of every message from this community, like `[EMER]`. Max 10 characters, must be unique in the network.

</details>

<details>

<summary><code>color</code></summary>

The tag's in-game color, as a hex code like `#4caf50`. Pick any color — it's how players tell communities apart at a glance.

</details>

<details>

<summary><code>spokeToken</code></summary>

A long random secret **you invent** — this community's password to the network. At least 20 random characters; a password generator is best. The exact same value goes into that server's plugin config (`relay.token`), and you send it to that community's admin. One token per community, never reuse.

</details>

<details>

<summary><code>guildId</code> and <code>chatChannelId</code></summary>

The community's Discord server id and the channel where network chat lives.

To get ids: in Discord, Settings → Advanced → turn on **Developer Mode**. Then right-click the server icon → **Copy Server ID** (that's `guildId`), and right-click the chat channel → **Copy Channel ID** (that's `chatChannelId`).

</details>

<details>

<summary><code>eventsChannelId</code> (optional)</summary>

**Default:** `0` (off)

A separate Discord channel for joins, deaths and advancements, so they don't clutter the chat channel.

</details>

<details>

<summary><code>linkedRoleId</code> (optional)</summary>

**Default:** `0` (off)

A Discord role that members automatically get when they link their Minecraft account with `/crosschat link`.

</details>

<details>

<summary><code>modLogChannelId</code> (optional)</summary>

**Default:** `0` (off)

A private staff channel in this community's Discord that receives their punishment log. See [Moderation](/plugins/community-chat/using-it/moderation.md).

</details>

<details>

<summary><code>staffChannelId</code> (optional)</summary>

**Default:** `0` (off)

A private staff channel in this community's Discord that is bridged to the network-wide staff chat. Anything typed there reaches staff members on every server (they see it in-game), and anything a staff member says with `/sc` in-game shows up here. Every community with a `staffChannelId` shares the same staff conversation. In-game, seeing and using `/sc` requires the `crosschat.staff` permission (defaults to server operators).

</details>
