Overview
This page is rebuilt from the current CoreChatX 2026.2.4 source defaults. Paper files live in plugins/CoreChatX/; Velocity files live in plugins/corechatx/.
- Current release:
2026.2.4 - Installable jars:
corechatx-paper-2026.2.4.jarandcorechatx-velocity-2026.2.4.jar - Paper target:
1.21.11 - Java target:
21 - Default network channel:
corechatx:main
Clean Setup Recommended For 2026.2.x
For the 2026.2.x line, a clean setup is recommended. Regenerate fresh Paper and Velocity config files, then manually reapply server-specific values such as deployment.*, channel formats, Discord token, Discord routes and required Discord role IDs.
This is especially important for existing Velocity networks. In PROXY, Velocity now owns cross-server runtime/user state; old Paper backend runtime YAML files should not be treated as authoritative network data.
Standalone Vs Proxy
One Paper server owns everything locally
Use deployment.mode: "STANDALONE". Runtime data, Discord links and optional Discord role checks are handled by that Paper server and its local YAML files.
Velocity owns shared runtime data
Use deployment.mode: "PROXY" on Paper and install the Velocity jar. Cross-server runtime writes go through Velocity and are stored per configured network-channel group.
Discord Bot Placement
- In
STANDALONE, the Discord bot is configured in Paperdiscord.yml. - In
PROXY, the bridge/linking bot is configured in Velocityvelocity-discord.yml. - In
PROXY, Paperdiscord.ymlcan optionally rundiscord.console.*as a separate console-only backend bot. - Use a different Discord bot token for each backend console bot to avoid duplicated gateway sessions.
- Velocity handles Discord bridge I/O, account linking, required-link-to-play and required-role-to-play for proxy groups.
Velocity Groups
Velocity network-channel can contain one or more comma-separated groups. Each group is isolated for PMs, chat routing, player directory, nicknames, mutes, ChatItem snapshot routing, Discord image transfer, Discord links, pending link codes and runtime data.
network-channel=corechatx:survival,corechatx:minigames
backend-groups.survival-1=corechatx:survival
backend-groups.minigames-1=corechatx:minigames
backend-groups.<velocity-server-name> pins are recommended when Velocity must decide login gates before the player reaches Paper, especially for required Discord link or role checks in multi-group setups.
Runtime Data Ownership
| Data | STANDALONE | PROXY |
|---|---|---|
| Player settings and nicknames | Paper YAML | Velocity group store |
| Ignore list and active channel | Paper YAML | Velocity group store |
| Mutes, global state, first-join count | Paper YAML | Velocity group store |
| Discord links and pending link codes | Paper YAML | Velocity group store |
| Discord bridge, player-list and channel descriptions | Paper discord.yml | Velocity velocity-discord.yml |
| Discord ChatItem image delivery | Paper bot sends attachments | Paper renders, Velocity bot sends attachments |
| Static chat/channel/message config | Paper files | Paper files plus Velocity config |
PlaceholderAPI Values
When PlaceholderAPI is installed and config.yml -> hooks.placeholderapi is enabled, CoreChatX exposes the following values to other PlaceholderAPI-aware plugins.
%corechatx_player_nickname%
Visible CoreChatX nickname
Returns the same display value as the internal {player_nickname} placeholder.
Uses the configured nicknames.prefix only when the player has a custom nickname. Otherwise it returns the real Minecraft name.
%corechatx_first_join_date%
Recorded first join date
Returns the player's first recorded join date formatted as yyyy-MM-dd HH:mm:ss.
Returns an empty value when CoreChatX has not recorded a first join date for that player yet.
%corechatx_messages_count%
Public message count
Returns the persisted number of public chat messages CoreChatX has counted for that player.
The counter follows the same runtime data owner as the rest of the player state.
Paper Files
The following blocks are the complete bundled Paper defaults, including comments.
config.ymlMain deployment identity, hooks, logging, nickname behavior, first join and join/quit behavior.
# Core plugin settings.
deployment:
# STANDALONE = Paper-only mode. Runtime player data is stored in this backend's YAML files.
# PROXY = Velocity-backed network mode. Runtime player data is owned by the CoreChatX Velocity module.
# Changing this mode requires a full restart.
mode: "STANDALONE"
require-full-restart-on-mode-change: true
# Backend id used for proxy routing and bridge source labels.
server-id: "paper-1"
# Plugin messaging channel shared with the Velocity module.
# In PROXY mode this also selects the isolated Velocity data/routing group for this backend.
network-channel: "corechatx:main"
# Global switch for Discord / Telegram chat bridge runtime.
# Discord console-only bots may still start through discord.yml -> discord.console.*.
bridges-allowed: true
# When false, Paper still boots in PROXY mode but proxy transport is intentionally disabled.
# Cross-server chat, PM routing, player directory sync, and proxy-owned runtime data operations will not run.
network-features-allowed: false
pending-pm-timeout-seconds: 20
debug: false
hooks:
# If true, PlaceholderAPI placeholders inside CoreChatX config formats are parsed when the plugin is present.
placeholderapi: true
# If true, LuckPerms group prefixes are read when the plugin is present.
luckperms: true
logging:
public-chat: true
private-messages: true
broadcasts: true
reload: true
errors: true
player-data:
# STANDALONE only: toggle commands still save immediately; this mainly controls the fallback save on plugin disable.
# In PROXY mode player settings, nicknames, ignore lists, active channel, mutes, global state and Discord links are stored by Velocity.
auto-save-on-disable: true
nicknames:
# Prefix prepended to {player_nickname} only when the player has a custom nickname.
# Leave empty to show the nickname exactly as set with /nick.
# Example: "~" makes {player_nickname} render as ~Nick while {player_name} still renders the real Minecraft username.
prefix: ""
# false = /nick can change the visible name text and styling, for example IceWolf23X -> IceWolf.
# true = /nick can only change allowed colors/styles; the visible text after removing formatting must stay exactly the real Minecraft username.
# Example with true: IceWolf23X may use &cIceWolf23X, but not &cIceWolf.
change-only-colors: false
first-join:
enabled: true
counter-enabled: true
join-quit:
# LOCAL = announce only on the current Paper backend.
# NETWORK = in PROXY mode, Velocity owns true network join/leave announcements and uses velocity-messages.yml.
mode: "LOCAL"
join-enabled: true
quit-enabled: true
reload:
# A short summary is shown to the command sender after a successful reload.
show-summary: true
messages.ymlPlayer-facing messages, command feedback, nickname and Discord link/kick text.
# Main message file.
# Supported placeholders vary by message, but common ones include:
# {prefix}, {player_name}, {player_nickname}, {target_name}, {sender_name}, {message}, {seconds}, {count}, {setting}, {state}
prefix: "<dark_gray>[</dark_gray><gradient:#79d6b8:#5aa9ff>CoreChatX</gradient><dark_gray>]</dark_gray>"
errors:
no-permission: "{prefix} <red>You do not have permission to do that.</red>"
players-only: "{prefix} <red>Only players can use this command.</red>"
player-not-found: "{prefix} <red>That player is not online.</red>"
cannot-message-self: "{prefix} <red>You cannot message yourself.</red>"
empty-message: "{prefix} <red>Your message is empty after sanitization.</red>"
no-reply-target: "{prefix} <red>You do not have anyone to reply to.</red>"
invalid-chatitem-id: "{prefix} <red>This chat item preview is no longer available.</red>"
invalid-usage: "{prefix} <red>Usage: {usage}</red>"
runtime-storage-unavailable: "{prefix} <red>CoreChatX runtime data is temporarily unavailable. Try again in a moment.</red>"
reload:
success: "{prefix} <green>Reload complete.</green>"
summary: "{prefix} <gray>Modules reloaded: chat, pings, PMs, filter, chat items, player data hooks.</gray>"
commands:
corechatx-help:
header: "{prefix} <gray>Available CoreChatX subcommands:</gray>"
reload: "<gray>/corechatx reload</gray>"
settings: "<gray>/corechatx settings</gray>"
locale: "<gray>/corechatx locale [tag]</gray>"
itemcache: "<gray>/corechatx itemcache [warmup|status|cancel]</gray>"
locale:
current: "{prefix} <gray>Your active locale is <white>{locale}</white>.</gray>"
changed: "{prefix} <gray>Your locale is now <white>{locale}</white>.</gray>"
invalid: "{prefix} <red>Locale <white>{locale}</white> is not available on this server.</red>"
channels:
list: "{prefix} <gray>Available channels: <white>{channels}</white></gray>"
switched: "{prefix} <gray>Your active channel is now <white>{channel_name}</white>.</gray>"
not-found: "{prefix} <red>Channel <white>{channel_name}</white> does not exist.</red>"
disabled: "{prefix} <red>Channel <white>{channel_name}</white> is currently disabled.</red>"
no-send-permission: "{prefix} <red>You cannot send messages to that channel.</red>"
privacy:
ignore-disabled: "{prefix} <red>Ignore commands are currently disabled.</red>"
ignore-self: "{prefix} <red>You cannot ignore yourself.</red>"
ignore-limit: "{prefix} <red>You cannot ignore more than <white>{limit}</white> players.</red>"
already-ignoring: "{prefix} <yellow>You are already ignoring <white>{target_name}</white>.</yellow>"
not-ignoring: "{prefix} <yellow>You are not ignoring <white>{target_name}</white>.</yellow>"
ignore-added: "{prefix} <gray>You are now ignoring <white>{target_name}</white>.</gray>"
ignore-removed: "{prefix} <gray>You are no longer ignoring <white>{target_name}</white>.</gray>"
ignore-list: "{prefix} <gray>Ignored players: <white>{targets}</white></gray>"
pm-toggled: "{prefix} <gray>Private messages are now <white>{state}</white>.</gray>"
moderation:
mute-disabled: "{prefix} <red>Mute commands are currently disabled.</red>"
mutechat-disabled: "{prefix} <red>Global chat mute is currently disabled.</red>"
muted-public: "{prefix} <red>You are muted and cannot use public chat right now.</red>"
muted-private: "{prefix} <red>You are muted and cannot send private messages right now.</red>"
chat-muted: "{prefix} <red>Public chat is currently muted.</red>"
chat-muted-toggled: "{prefix} <gray>Global chat mute is now <white>{state}</white>.</gray>"
anti-repeat: "{prefix} <red>Please do not repeat the same message.</red>"
anti-caps: "{prefix} <red>Please avoid excessive caps.</red>"
mute-success: "{prefix} <gray>Muted <white>{target_name}</white>. Reason: <white>{reason}</white></gray>"
unmute-success: "{prefix} <gray>Unmuted <white>{target_name}</white>.</gray>"
clear-chat-notice: "{prefix} <gray>Chat was cleared by <white>{sender_name}</white>.</gray>"
clear-chat-sender: "{prefix} <gray>Cleared chat for <white>{count}</white> online player(s).</gray>"
cooldown:
public: "{prefix} <yellow>You must wait <white>{seconds}</white> more second(s) before chatting again.</yellow>"
pm: "{prefix} <yellow>You must wait <white>{seconds}</white> more second(s) before sending another private message.</yellow>"
ping:
toggles:
# Used by /ping <sound|actionbar> status with placeholders {setting} and {state}.
status: "{prefix} <gray>Ping <white>{setting}</white> notifications are currently <white>{state}</white>.</gray>"
sound-changed: "{prefix} <gray>Ping sound notifications are now <white>{state}</white>.</gray>"
actionbar-changed: "{prefix} <gray>Ping actionbar notifications are now <white>{state}</white>.</gray>"
state-on: "<green>enabled</green>"
state-off: "<red>disabled</red>"
# Used when a player is pinged by a mention or a custom ping.
notification-actionbar: "<gold>Ping:</gold> <yellow>{sender_name}</yellow> mentioned you."
notification-sound: "ENTITY_EXPERIENCE_ORB_PICKUP"
notification-volume: 0.85
notification-pitch: 1.25
private-messages:
to-sender: "<dark_gray>[</dark_gray><light_purple>PM</light_purple><dark_gray>]</dark_gray> <gray>you -> </gray><white>{target_name}</white><dark_gray>: </dark_gray>{message}"
to-target: "<dark_gray>[</dark_gray><light_purple>PM</light_purple><dark_gray>]</dark_gray> <white>{sender_name}</white><gray> -> you</gray><dark_gray>: </dark_gray>{message}"
spy: "<dark_gray>[</dark_gray><red>SPY</red><dark_gray>]</dark_gray> <white>{sender_name}</white><gray> -> </gray><white>{target_name}</white><dark_gray>: </dark_gray>{message}"
disabled-target: "{prefix} <red>That player has private messages disabled.</red>"
blocked-by-target: "{prefix} <red>That player is not accepting messages from you.</red>"
remote-unavailable: "{prefix} <red>The proxy transport could not forward that private message right now.</red>"
received-sound: "BLOCK_NOTE_BLOCK_BELL"
received-volume: 0.85
received-pitch: 1.1
socialspy-on: "{prefix} <gray>Social spy is now <green>enabled</green>.</gray>"
socialspy-off: "{prefix} <gray>Social spy is now <red>disabled</red>.</gray>"
broadcast:
format: "<dark_gray>[</dark_gray><gold>Broadcast</gold><dark_gray>]</dark_gray> <white>{sender_name}</white><dark_gray>: </dark_gray><gold>{message}</gold>"
nickname:
changed: "{prefix} <gray>Your nickname is now <white>{nickname}</white>.</gray>"
cleared: "{prefix} <gray>Your nickname has been cleared.</gray>"
changed-other: "{prefix} <gray>Set <white>{target_name}</white>'s nickname to <white>{nickname}</white>.</gray>"
cleared-other: "{prefix} <gray>Cleared <white>{target_name}</white>'s nickname.</gray>"
invalid: "{prefix} <red>That nickname is invalid. Use one visible word after formatting is removed.</red>"
duplicate: "{prefix} <red>That nickname is already used by another player or matches another player's real username.</red>"
name-change-disabled: "{prefix} <red>Nicknames can only change colors/styles. The visible text must stay exactly the player's real Minecraft username.</red>"
too-long: "{prefix} <red>Nicknames can be at most <white>{limit}</white> visible characters.</red>"
realname: "{prefix} <white>{player_nickname}</white><gray>'s real name is </gray><white>{player_name}</white><gray>.</gray>"
realname-not-found: "{prefix} <red>No custom nickname matches that value.</red>"
discord:
link-code: "{prefix} <gray>Use Discord command <white>/link code:{code}</white> within <white>{minutes}</white> minute(s) to link your account.</gray>"
link-required-kick: "<red>You must link your Discord account to play.</red>\n<gray>Use Discord command </gray><white>/link code:{code}</white><gray> within </gray><white>{minutes}</white><gray> minute(s).</gray>"
missing-required-role-kick: "<red>Your Discord account is linked, but you do not have the required Discord role to play.</red>"
role-check-unavailable-kick: "<red>Discord role verification is temporarily unavailable. Try again later.</red>"
already-linked: "{prefix} <yellow>Your Minecraft account is already linked to Discord. Use <white>/discord unlink</white> first.</yellow>"
linking-disabled: "{prefix} <red>Discord account linking is currently disabled.</red>"
link-unavailable: "{prefix} <red>Discord account linking data is temporarily unavailable. Try again later.</red>"
linked-status: "{prefix} <gray>Your Minecraft account is linked to Discord user id <white>{discord_id}</white>.</gray>"
not-linked: "{prefix} <yellow>No Discord account is linked.</yellow>"
unlinked: "{prefix} <gray>Discord account link removed.</gray>"
admin-linked: "{prefix} <gray>Linked <white>{player_name}</white> to Discord user id <white>{discord_id}</white>.</gray>"
invalid-discord-id: "{prefix} <red>That Discord user id is invalid.</red>"
chat:
no-message-sent: "{prefix} <yellow>Nothing was sent because the message is empty after sanitization.</yellow>"
join-quit:
join: "<dark_gray>[</dark_gray><green>+</green><dark_gray>]</dark_gray> <white>{player_nickname}</white>"
quit: "<dark_gray>[</dark_gray><red>-</red><dark_gray>]</dark_gray> <white>{player_nickname}</white>"
first-join: "<dark_gray>[</dark_gray><gradient:#79d6b8:#5aa9ff>Welcome</gradient><dark_gray>]</dark_gray> <white>{player_nickname}</white><gray> is joining for the first time as player </gray><white>#{count}</white><gray>.</gray>"
chatitems:
# Hover shown on clickable chat preview tokens.
click-to-open: "<gray>Click to open the saved preview.</gray>"
expired: "{prefix} <red>This preview has expired or was cleared during reload/restart.</red>"
chat.ymlPublic chat formatting, moderation gates and message processing rules.
# Public chat formatting and moderation settings.
public-chat:
enabled: true
# Supported placeholders inside the format:
# {plugin_prefix}, {channel_prefix}, {rank_prefix}, {player_name}, {player_nickname}, {message}
# {player_name} is always the real Minecraft username.
# {player_nickname} is the custom nickname when set, otherwise the real Minecraft username.
# Layout inspired by the older NetworkChat proxy format:
# prefix + player name + italic separator + processed message.
# CoreChatX keeps its own default palette instead of copying the old colors verbatim.
format: "{plugin_prefix} {channel_prefix}{rank_prefix}<white>{player_nickname}</white><dark_gray><italic>» </italic></dark_gray>{message}"
# Optional group-specific format overrides keyed by LuckPerms primary group.
# These are used only when channels.yml -> format is blank for the active channel.
# Keys must match the LuckPerms primary group in lowercase.
group-formats:
owner: "{plugin_prefix} {channel_prefix}{rank_prefix}<white>{player_nickname}</white><dark_gray><italic>» </italic></dark_gray>{message}"
admin: "{plugin_prefix} {channel_prefix}{rank_prefix}<white>{player_nickname}</white><dark_gray><italic>» </italic></dark_gray>{message}"
mod: "{plugin_prefix} {channel_prefix}{rank_prefix}<white>{player_nickname}</white><dark_gray><italic>» </italic></dark_gray>{message}"
vip: "{plugin_prefix} {channel_prefix}{rank_prefix}<white>{player_nickname}</white><dark_gray><italic>» </italic></dark_gray>{message}"
default: "{plugin_prefix} {channel_prefix}{rank_prefix}<gray>{player_nickname}</gray><dark_gray><italic>» </italic></dark_gray>{message}"
plugin-prefix: "<dark_gray>[</dark_gray><gradient:#79d6b8:#5aa9ff>Chat</gradient><dark_gray>]</dark_gray>"
# Applied to non-global active channels such as local or staff.
channel-prefix-format: "<dark_gray>[</dark_gray><white>{channel_name}</white><dark_gray>]</dark_gray> "
fallback-rank-prefix: ""
mentions:
enabled: true
# Mention matching accepts both Steve and @Steve when the token matches a local or network-online player exactly.
# If disabled, names are left as normal text and no mention notification logic runs.
# The resolver accepts real usernames and custom plain nicknames; this format controls what the rendered mention displays.
# {player_name} is the real Minecraft username. {player_nickname} is the visible nickname when set.
token-format: "<#79d6b8>@{player_nickname}</#79d6b8>"
cooldowns:
public:
enabled: true
seconds: 2
private-messages:
enabled: false
seconds: 2
channels.ymlChannel definitions, scope, permissions, mention rules, ChatItem rules and bridge export options.
# Channel defaults.
# In STANDALONE mode, NETWORK still behaves as a normal local channel unless the proxy bridge is enabled.
# In PROXY mode, only channels with scope NETWORK are forwarded cross-server.
# SERVER and LOCAL_RADIUS always stay backend-local.
channels:
global:
enabled: true
default: true
scope: "NETWORK"
permission-send: ""
permission-receive: ""
# Controls whether player names and custom ping tokens are parsed by source.
allow-mentions:
from-minecraft: true
from-discord: true
from-telegram: true
# If false, [item]/[inv]/[ec] tokens stay plain text in this channel.
allow-chatitems: true
# If false, successful player chat in this channel does not create overhead chat bubbles.
allow-chat-bubbles: true
# If true, locally-sent messages in this channel may be exported to Discord / Telegram bridges.
export-to-bridges: true
# Optional per-channel format. Leave blank to use chat.yml -> public-chat.format.
format: ""
discord:
# Optional Discord format for Minecraft -> Discord messages from this channel.
# Leave blank to use discord.yml -> discord.format.
outbound-format: ""
# Optional Discord format for Discord -> Minecraft messages routed to this channel.
# Leave blank to use discord.yml -> discord.inbound.format.
inbound-format: ""
# Account-link requirement override for Discord -> Minecraft messages routed to this CoreChatX channel.
# Values: inherit, true, false.
require-linked-inbound: "inherit"
telegram:
# Optional Telegram format for Minecraft -> Telegram messages from this channel.
# Leave blank to use telegram.yml -> telegram.format.
outbound-format: ""
# Optional Telegram format for Telegram -> Minecraft messages routed to this channel.
# Leave blank to use the regular CoreChatX channel chat format.
inbound-format: ""
local:
enabled: true
default: false
scope: "LOCAL_RADIUS"
radius: 100
permission-send: "corechatx.channel.local"
permission-receive: ""
allow-mentions:
from-minecraft: true
from-discord: true
from-telegram: true
allow-chatitems: true
allow-chat-bubbles: true
export-to-bridges: false
format: ""
discord:
outbound-format: ""
inbound-format: ""
require-linked-inbound: "inherit"
telegram:
outbound-format: ""
inbound-format: ""
staff:
enabled: true
default: false
scope: "NETWORK"
permission-send: "corechatx.channel.staff"
permission-receive: "corechatx.staff"
allow-mentions:
from-minecraft: true
from-discord: true
from-telegram: true
allow-chatitems: false
allow-chat-bubbles: false
export-to-bridges: true
format: ""
discord:
outbound-format: ""
inbound-format: ""
require-linked-inbound: "inherit"
telegram:
outbound-format: ""
inbound-format: ""
pings.ymlMention and custom ping behavior, sounds, actionbar text and permission gates.
# Mention and custom ping behaviour.
mentions:
# Global switches for notification delivery once a target is selected.
notify-sound: true
notify-actionbar: true
custom-pings:
# Each entry is generic and fully data-driven:
# trigger = visible token matched in chat
# use-permission = who may activate it
# receive-permission = who may be targeted; leave blank for everyone online
# discord-roles = Discord role IDs allowed to activate this ping from Discord; empty blocks Discord usage
# bypass-toggle = if true, recipients are notified even when they disabled ping sound/actionbar
# token-format = how the token itself is rendered in chat
all:
trigger: "@all"
use-permission: "corechatx.ping.use.all"
receive-permission: ""
discord-roles: []
bypass-toggle: false
token-format: "<#79d6b8>{trigger}</#79d6b8>"
help:
trigger: "@help"
use-permission: "corechatx.ping.use.help"
receive-permission: "corechatx.ping.receive.help"
discord-roles: []
bypass-toggle: false
token-format: "<#5aa9ff>{trigger}</#5aa9ff>"
staff:
trigger: "@staff"
use-permission: "corechatx.ping.use.staff"
receive-permission: "corechatx.staff"
discord-roles: []
bypass-toggle: true
token-format: "<#ff8f8f>{trigger}</#ff8f8f>"
privacy.ymlDefault private-message, social spy and ignore behavior.
# Privacy defaults.
private-messages:
enabled-by-default: true
allow-staff-bypass: true
staff-bypass-permission: "corechatx.staff"
ignore:
enabled: true
max-ignored-players: 200
# If true, ignored players also stop mention/custom-ping notifications.
block-mentions-from-ignored: true
moderation.ymlMute, global chat mute, anti-caps, anti-repeat and filter behavior.
# Moderation defaults.
mute:
enabled: true
# If true, active mutes also block /msg and /reply.
block-private-messages: true
default-reason: "No reason provided"
mutechat:
enabled: true
anti-repeat:
enabled: true
history-window: 3
block-identical: true
anti-caps:
enabled: false
min-length: 8
max-uppercase-ratio: 0.7
filter.ymlWord filter matching and replacement configuration.
# Word filter configuration.
enabled: true
# The filter censors and still sends the message.
blocked-words:
- idiota
- stupido
replacement-character: "*"
hover-original:
enabled: false
text: "<gray>Original term:</gray> <red>{word}</red>"
chatitems.ymlChatItem token configuration for held item, inventory, armor, hotbar and ender chest previews.
# Chat item token configuration.
# Every token is matched on sanitized player text.
# If the sender lacks the configured permission, the message is still sent
# but that token stays plain text and no preview is created.
tokens:
item:
# [item] upgrades to [shulker] automatically when the held item is a shulker box
# and the sender has corechatx.chatitem.shulker.
# The snapshot stores the held item exactly as it looked when the message was sent.
aliases: [ "[item]", "[i]" ]
permission: "corechatx.chatitem.item"
token-format: "<#79d6b8>[item]</#79d6b8>"
shulker-token-format: "<#5fc7c2>[shulker]</#5fc7c2>"
armor:
# Opens a read-only preview with helmet, chestplate, leggings, boots, and offhand.
aliases: [ "[armor]" ]
permission: "corechatx.chatitem.armor"
token-format: "<#6fb6ff>[armor]</#6fb6ff>"
hotbar:
# Shows the first 9 inventory slots from the sender at message time.
aliases: [ "[hotbar]" ]
permission: "corechatx.chatitem.hotbar"
token-format: "<#8bc8ff>[hotbar]</#8bc8ff>"
inventory:
# Includes the main inventory plus armor and offhand in a read-only snapshot.
aliases: [ "[inventory]", "[inv]" ]
permission: "corechatx.chatitem.inventory"
token-format: "<#5aa9ff>[inventory]</#5aa9ff>"
enderchest:
# Opens the sender ender chest snapshot captured when the message was sent.
aliases: [ "[enderchest]", "[ender]", "[ec]" ]
permission: "corechatx.chatitem.enderchest"
token-format: "<#7db8ff>[enderchest]</#7db8ff>"
previews:
# Snapshots are ephemeral runtime data. Reload clears them to avoid mixing old and new state.
# Expired or cleared previews will no longer open from old chat messages.
expire-after-minutes: 30
titles:
# {player_name} is always the real snapshot owner's username.
# {player_nickname} uses the owner's custom nickname when available.
item: "<#79d6b8>{player_nickname}'s item</#79d6b8>"
shulker: "<#5fc7c2>{player_nickname}'s shulker</#5fc7c2>"
armor: "<#6fb6ff>{player_nickname}'s armor</#6fb6ff>"
hotbar: "<#8bc8ff>{player_nickname}'s hotbar</#8bc8ff>"
inventory: "<#5aa9ff>{player_nickname}'s inventory</#5aa9ff>"
enderchest: "<#7db8ff>{player_nickname}'s ender chest</#7db8ff>"
discord-images:
# Global toggle for Discord ChatItem inventory snapshots.
# When false, CoreChatX does not render, download assets for, or send ChatItem PNG attachments to Discord.
# Minecraft chat tokens and in-game clickable previews continue to work normally.
# When true, ChatItem tokens sent from Minecraft to Discord also send a rendered PNG attachment/embed.
# Embed colors are derived from previews.titles.* and token-format values above.
enabled: true
# Maximum unique ChatItem images attached per chat message. The protocol hard-caps this to 3.
max-images-per-message: 3
embed:
# Controls the Discord embed title for each ChatItem image.
# Set a value to "" to omit the title completely.
# For [item], this text is rendered into the attached PNG with the Minecraft bitmap font
# instead of being sent as Discord embed text.
# Custom item names use Minecraft's default italic tooltip style unless the rendered component overrides it.
# Common placeholders: {player_name}, {player_nickname}, {type}, {token}, {plain_text}.
# Item placeholders: {item_name}, {material}, {durability}, {durability_line}, {enchantments}, {lore}.
# Extra item tooltip placeholders: {attributes}, {potion_effects}, {banner_patterns}, {armor_trim},
# {unbreakable}, {can_place_on}, {can_break}, {book_metadata}, {firework_data}, {tooltip_extra}.
title:
item: "{item_name}"
armor: "{player_nickname}'s armor"
hotbar: "{player_nickname}'s hotbar"
inventory: "{player_nickname}'s inventory"
enderchest: "{player_nickname}'s ender chest"
shulker: "{player_nickname}'s shulker"
# Controls the Discord embed description.
# For [item], these lines are rendered into the transparent attached PNG with the item icon.
# Custom lore lines use Minecraft's default italic tooltip style; enchantments, attributes and metadata do not.
# Each list entry becomes one rendered line.
# For [item], each detail placeholder adds its own blank line only when content exists.
# Empty rendered lines are removed, so missing metadata does not leave blank lines.
# Use [] to omit the description completely for that ChatItem type.
description:
item:
- "{enchantments}"
- "{attributes}"
- "{potion_effects}"
- "{lore}"
- "{armor_trim}"
- "{banner_patterns}"
- "{unbreakable}"
- "{can_place_on}"
- "{can_break}"
- "{book_metadata}"
- "{firework_data}"
- "{durability_line}"
armor: []
hotbar: []
inventory: []
enderchest: []
shulker: []
item-menu:
# Adds one or more Discord dropdown menus below non-[item] ChatItem images.
# Selecting an entry sends the selected item preview as an ephemeral message visible only to that Discord user.
# The menu expires with the same lifetime as the in-game clickable ChatItem preview token.
enabled: true
# Text shown inside each dropdown before a Discord user selects an item.
placeholder: "Inspect an item"
# Discord option label. Keep it short: Discord limits labels to 100 characters.
# Placeholders: {slot}, {slot_index}, {item_display_name}, {item_name}, {amount}, {material}, {durability}, {durability_line}, {enchantments}, {lore}.
# Extra tooltip placeholders are also available: {attributes}, {potion_effects}, {banner_patterns}, {armor_trim},
# {unbreakable}, {can_place_on}, {can_break}, {book_metadata}, {firework_data}, {tooltip_extra}.
label-format: "Slot {slot}: {item_display_name}"
# Optional Discord option description. Set to "" to omit it.
description-format: "x{amount} - {material}"
expired-message: "This ChatItem preview has expired."
unavailable-message: "That item preview is unavailable."
render:
# Pixel scale used by inventory-like image renders: armor, hotbar, inventory, ender chest and shulker.
# Higher values produce larger PNG files.
scale: 8
# Pixel scale for the Discord [item] details panel: Minecraft font, tooltip background, spacing,
# and the base item icon before the icon-only multiplier below is applied.
# Set this to 0 or a negative value to reuse "scale" above.
single-item-details-scale: 8
# Multiplies only the item icon inside the Discord [item] details panel.
# Text and tooltip background keep single-item-details-scale.
single-item-details-icon-multiplier: 4
assets:
# "auto" uses the running Minecraft server version. A fixed version or latest-release can also be used.
minecraft-version: "auto"
# When true, CoreChatX downloads/extracts vanilla client assets into its local cache.
# No vanilla Minecraft assets are bundled inside the plugin jar.
download-vanilla-assets: true
# Optional resource pack zip/folder paths. Relative paths are resolved from the CoreChatX plugin folder.
resource-packs: []
network:
# Network mode sends only lightweight snapshot refs in chat packets.
# Multiple ChatItem tokens in the same message share one snapshot bundle with per-token views.
# The full bundle is fetched from the source backend when a remote player clicks a view.
request-timeout-seconds: 5
# Maximum unique snapshot bundle refs attached to one network chat message.
# The plugin-message protocol currently hard-caps the effective value to 3.
max-snapshots-per-message: 3
max-compressed-bytes: 30000
max-uncompressed-bytes: 2097152
max-item-bytes: 262144
keywords.ymlClickable keyword aliases such as rules, Discord, store, vote and map.
# Interactive keyword token configuration.
# Each keyword replaces one or more literal aliases with one MiniMessage renderer.
keywords:
discord:
enabled: true
tokens: [ "[discord]", "[dc]" ]
renderer: "<blue><hover:show_text:'<gray>Join our Discord</gray>'><click:open_url:'https://discord.gg/example'>discord</click></hover></blue>"
allow-placeholderapi: false
permission: "corechatx.keywords.use.discord"
enabled-channels: []
disabled-channels: []
rules:
enabled: true
tokens: [ "[rules]" ]
renderer: "<yellow><hover:show_text:'<gray>Click to read the rules</gray>'><click:run_command:'/rules'>rules</click></hover></yellow>"
allow-placeholderapi: false
permission: ""
enabled-channels: []
disabled-channels: []
chatbubbles.ymlOptional overhead chat bubble rendering behavior.
# Chat bubbles / overhead chat configuration.
enabled: true
default-enabled: true
permission: "corechatx.chatbubbles.use"
enabled-channels: []
disabled-channels: [ "staff" ]
max-active-bubbles: 3
base-height: 0.75
stack-offset: 0.32
max-visible-distance: 32
base-duration-ticks: 80
ticks-per-character: 2
max-duration-ticks: 160
max-plain-length: 80
max-line-length: 28
shadow: true
see-through: false
text-color: "#FFFFFF"
background-color: "#80000000"
hide-while-sneaking: false
hide-if-invisible: true
world-filter:
enabled: false
disabled-worlds: []
renderer:
format: "{message}"
discord.ymlPaper Discord settings. In PROXY, bridge/linking stays on Velocity; Paper may run console-only bots.
# Discord integration for Paper.
# STANDALONE owns chat bridge, account linking and optional console here.
# PROXY keeps chat bridge/account linking on Velocity, but may still run a local console-only bot per backend.
account-linking:
# Master switch for Discord-Minecraft account linking.
# STANDALONE: this backend owns the bot, link codes, linked accounts and optional Discord role checks.
# PROXY: configure the bot, Discord bridge routes and login gates in Velocity's velocity-discord.yml instead.
# Paper keeps this file for standalone setups and local formatting only.
enabled: false
# If true, linked Discord members get their server nickname synced to their Minecraft nickname.
# Falls back to the Minecraft player name when no custom nickname is set. In PROXY, configure this on Velocity.
sync-mc-name: false
# If true, unlinked Discord users cannot write through routed Discord inbound channels.
# Route and channel overrides can still force true/false for specific destinations.
require-linked: false
# If true, unlinked Minecraft players are kicked after joining the backend with a code to use in Discord command /link code:<code>.
require-linked-to-play: false
required-play-roles:
# Extra gate for require-linked-to-play. When enabled, linked players must also have at least one listed Discord role.
enabled: false
# Discord guild/server id used for the role check.
# If blank and the standalone Paper bot is in one guild, that guild is used automatically.
guild-id: ""
# Discord role ids allowed to join. Empty list disables the role gate and logs a warning when enabled.
role-ids: []
# If true, kick linked players when Discord role verification cannot be completed.
deny-if-unverifiable: true
# Deletes blocked unlinked messages when the bot has Discord's Manage Messages permission.
delete-unlinked-messages: true
# Sends a private Discord DM explaining why the message was blocked.
dm-unlinked-users: true
# Link codes generated by /discord link or required-link-to-play expire after this many minutes.
code-expire-minutes: 10
# If true, linked Discord users may chat while the Minecraft account is offline when stored data and LuckPerms data can be resolved.
allow-offline-linked-players: true
# If true, Minecraft mute state blocks linked Discord inbound messages.
enforce-minecraft-mutes: true
# If true, the linked Minecraft account must have permission to send to the target CoreChatX channel.
enforce-channel-send-permission: true
# Rate limit for warnings when CoreChatX cannot delete a Discord message because the bot lacks Manage Messages.
missing-manage-messages-warning-seconds: 300
# STANDALONE only: Discord slash command names registered by the backend that runs the Discord bot.
# If another plugin already owns /link, change these names before starting the bot.
link-command-name: "link"
unlink-command-name: "unlink"
messages:
unlinked-dm: "Link your Minecraft account before chatting in this channel. Run /discord link in-game, then use the Discord /link command with that code here."
linked: "Your Discord account is now linked to {player_name}."
unlinked: "Your Discord account has been unlinked."
not-linked: "This Discord account is not linked to a Minecraft account."
already-linked: "This Discord account or Minecraft account is already linked. Unlink it first."
code-not-found: "That link code is invalid or expired."
minecraft-denied: "Your linked Minecraft account cannot send messages to that channel right now."
discord:
# STANDALONE: enables the Paper-owned Discord bot for bridge/linking/console.
# PROXY: enables only discord.console.* on this backend; bridge/account-linking targets must be configured on Velocity.
enabled: false
bot-token: ""
default-channel-id: ""
format: "[{source_server}] [{channel_id}] {rank_prefix}{sender_name}: {plain_text}"
# If true, Minecraft -> Discord bridge output breaks Discord mention tokens before sending.
# This prevents players from pinging Discord users, roles, @everyone or @here by typing raw Discord mention syntax in Minecraft.
prevent-mentions-from-minecraft: true
connection-messages:
# STANDALONE only. In PROXY, configure Discord join/quit mirrors in Velocity's velocity-discord.yml.
# If true, CoreChatX mirrors accepted join, first-join and quit messages to Discord.
# Messages are sent only when the Minecraft join/quit message is actually announced.
enabled: false
# Discord channel ids that should receive join/quit mirrors.
# Empty list = discord.default-channel-id.
channels: []
# Tokens: {source}, {source_type}, {source_server}, {channel_id}, {sender_name}, {rank_prefix}, {plain_text}, {message}
format: "{plain_text}"
# Optional action-specific plain-text formats. Leave empty to use format above.
join-format: ""
first-join-format: ""
quit-format: ""
embed:
# If true, join/quit mirrors are sent as a Discord embed instead of plain content.
enabled: false
# Hex color used for the embed side bar.
color: "#57F287"
# Optional action-specific colors. Leave empty to use color above.
join-color: "#57F287"
first-join-color: "#57F287"
quit-color: "#ED4245"
# Leave title empty for a compact embed with only the description.
title: ""
# Supports the same tokens as connection-messages.format.
description: "{plain_text}"
# Optional action-specific descriptions. Leave empty to use description above.
join-description: ""
first-join-description: ""
quit-description: ""
event-messages:
# STANDALONE only. In PROXY, configure event mirrors in Velocity's velocity-discord.yml.
# If true, CoreChatX mirrors supported server events to Discord.
# Supported source_type values for now: death, advancement.
enabled: false
# CoreChatX channel ids that should receive event mirrors.
# Empty list = all enabled channels with export-to-bridges: true and a Discord target.
channels: []
# Tokens: {source}, {source_type}, {source_server}, {channel_id}, {sender_name}, {rank_prefix}, {plain_text}, {message}
format: "{plain_text}"
# Optional event-specific plain-text formats. Leave empty to use format above.
death-format: ""
advancement-format: ""
embed:
# Event mirrors are sent as embeds when enabled.
enabled: true
color: "#5865F2"
death-color: "#ED4245"
advancement-color: "#FEE75C"
title: ""
description: "{plain_text}"
death-description: ""
advancement-description: ""
console:
# Allows this Paper backend to act as a Discord console bot even when chat bridge/account linking are disabled.
# In PROXY mode this is the only Paper Discord feature that can run.
# Use a separate Discord bot token per backend console to avoid duplicated gateway sessions.
enabled: false
# Discord channel id used as the console channel.
channel-id: ""
# Messages starting with this prefix are executed as Paper console commands.
# Set to "" to execute every message in the console channel as a command.
command-prefix: "!"
# If true, Paper console log lines are mirrored live to the Discord console channel.
live-log: true
# Sends a short Discord acknowledgement after dispatching a command.
send-command-feedback: true
# Empty allow lists mean anyone who can write in the configured Discord channel can run commands.
allowed-user-ids: []
allowed-role-ids: []
max-log-line-length: 1800
player-list:
# STANDALONE only. In PROXY mode configure the player-list command in Velocity's velocity-discord.yml.
# Shows online players from this Paper server.
enabled: false
# Text command listened in Discord channels visible to the bot. Set to "" to disable the text command.
command: "!playerlist"
# Also register a slash command. Slash commands can use true ephemeral replies.
register-slash-command: true
slash-command-name: "playerlist"
# CHANNEL = public embed, DM = private DM, EPHEMERAL = slash-only private reply.
# Text commands cannot be ephemeral, so EPHEMERAL falls back to DM for !playerlist.
response-visibility: "CHANNEL"
max-players: 80
embed:
color: "#5865F2"
title: "Online players ({count})"
empty-description: "No players are currently online."
# Tokens: {player_name}, {player_nickname}, {server}
line-format: "- {player_nickname}"
more-format: "... and {hidden_count} more."
channel-description:
# STANDALONE only. In PROXY mode configure channel descriptions in Velocity's velocity-discord.yml.
# Updates the description/topic of Discord text channels.
enabled: false
# Discord rate limits channel metadata updates; keep this at 60 seconds or higher.
interval-seconds: 300
triggers:
# Queue a debounced description update when a player joins this standalone server.
on-connection: true
# Queue a debounced description update when a player leaves this standalone server.
on-disconnection: true
# When many players join/quit at once, CoreChatX waits this long after the last event before updating Discord.
event-debounce-seconds: 5
# Each entry updates one Discord text channel description.
# The description string is passed through PlaceholderAPI when PlaceholderAPI is installed and enabled.
# Internal placeholders:
# {online} = players online on this standalone server.
# {online_in_group} = same as {online} in STANDALONE.
entries:
# - channel-id: "123456789012345678"
# description: "Players {online}/1000"
server-status:
# STANDALONE only. In PROXY mode configure proxy/backend status messages in Velocity's velocity-discord.yml.
# Sends Discord embed messages when this standalone server starts and stops cleanly.
enabled: false
default:
enabled: true
# Discord channel ids. Empty falls back to discord.default-channel-id.
channels: []
embed:
online:
enabled: true
color: "#57F287"
title: "Server online"
description: "`{server}` is now online."
offline:
enabled: true
color: "#ED4245"
title: "Server offline"
description: "`{server}` is now offline."
# Per standalone server override. Keys must match deployment.server-id.
# Any missing field inherits from default; write a custom title/description to avoid showing the technical {server}.
servers:
# paper-1:
# channels:
# - "123456789012345678"
# embed:
# online:
# title: "Survival online"
# description: "The survival server is ready."
# Optional per-channel overrides:
# channel-overrides:
# global: "123456789012345678"
channel-overrides: {}
inbound:
enabled: false
default-channel: "global"
max-length: 400
# Format used for Discord -> Minecraft messages.
# Tokens: {source}, {source_type}, {channel_id}, {channel_prefix}, {sender_name}, {player_name}, {player_nickname}, {discord_name}, {discord_id}, {rank_prefix}, {role_color}, {plain_text}, {message}
# When account-linking is enabled and the Discord user is linked, {sender_name}, {player_name}, {player_nickname}, and {rank_prefix} use the linked Minecraft identity.
# Use {role_color} as a MiniMessage color tag, for example: "{role_color}{rank_prefix}</role_color> "
format: "{channel_prefix}[Discord] {role_color}{rank_prefix}</role_color>{sender_name}: {plain_text}"
# Optional per Discord route account-link override.
# Values: inherit, true, false.
# route-overrides:
# "123456789012345678":
# require-linked: true
route-overrides: {}
# Map Discord channel ids to CoreChatX channel ids.
# channel-routes:
# "123456789012345678": "staff"
channel-routes: {}
telegram.ymlTelegram bridge settings.
# Telegram bridge.
# Uses Telegram Bot API only.
# Inbound uses long polling through getUpdates(timeout=...).
# Outbound uses sendMessage.
# No webhook, no Telegram4J, no MTProto.
telegram:
enabled: false
bot-token: ""
# Fallback target for outbound messages when no per-channel target is configured.
# Can be a numeric chat id or a Bot API-supported @username target.
default-chat-id: ""
format: "[{source_server}] [{channel_id}] {sender_name}: {plain_text}"
outbound:
# Per-CoreChatX-channel Telegram targets.
# message-thread-id targets a Telegram forum topic when greater than 0.
channel-targets:
global:
chat-id: ""
message-thread-id: 0
staff:
chat-id: ""
message-thread-id: 0
inbound:
enabled: false
# Long polling timeout passed to Telegram getUpdates.
timeout-seconds: 30
# Small delay between normal long-poll cycles.
retry-delay-seconds: 3
# Backoff delay after network/API/parsing errors.
error-backoff-seconds: 10
skip-pending-on-start: true
max-length: 400
default-channel: "global"
# Display name used for Telegram -> Minecraft messages.
# Tokens: {source}, {source_type}, {sender_name}
# Set to "{sender_name}" to remove the [Telegram] prefix.
display-name-format: "[{source}] {sender_name}"
# Logs detected safe route keys to help configure groups/topics.
debug-route-detection: false
# Inbound route map.
# Keys can be "chatId" or "chatId:messageThreadId".
routes:
# "-1001111111111": "global"
# "-1001111111111:25": "staff"
storage.ymlStorage configuration and PROXY runtime authority notes.
# Storage defaults.
# STANDALONE runtime data uses local YAML repositories.
# PROXY runtime data is owned by Velocity; this file remains local backend configuration.
storage:
backend: "YAML"
sql:
enabled: false
type: "SQLITE"
host: "localhost"
port: 3306
database: "corechatx"
username: "user"
password: "password"
playerdata.ymlGenerated standalone runtime player state default.
players: {}
state.ymlGenerated standalone global state default.
first-joins:
count: 0
chat:
muted: false
locales/en_us.ymlLocale override file. Missing keys fall back to messages.yml.
# Locale overrides for player-facing messages.
# Missing keys fall back to messages.yml.
general:
player_not_found: "<red>Player not found.</red>"
commands:
corechatx-help:
header: "{prefix} <gray>Available CoreChatX subcommands:</gray>"
reload: "<gray>/corechatx reload</gray>"
settings: "<gray>/corechatx settings</gray>"
locale: "<gray>/corechatx locale [tag]</gray>"
itemcache: "<gray>/corechatx itemcache [warmup|status|cancel]</gray>"
privacy:
ignore:
usage: "<red>Usage: /ignore <player></red>"
self: "<red>You cannot ignore yourself.</red>"
already: "<yellow>You are already ignoring that player.</yellow>"
success: "<gray>You are now ignoring <white>{target_name}</white>.</gray>"
moderation:
clear-chat-sender: "{prefix} <gray>Cleared chat for <white>{count}</white> online player(s).</gray>"
plugin.ymlPaper plugin metadata, commands, permissions and soft dependencies.
name: CoreChatX
description: ${project.description}
prefix: CoreChatX
version: ${project.version}
main: me.icewolf23.corechatx.paper.bootstrap.CoreChatXPaperPlugin
api-version: '1.21'
load: POSTWORLD
authors: [ IceWolf23X ]
softdepend: [ PlaceholderAPI, LuckPerms ]
libraries:
- net.kyori:adventure-text-minimessage:${adventure.version}
- net.kyori:adventure-text-serializer-legacy:${adventure.version}
- net.kyori:adventure-text-serializer-gson:${adventure.version}
- com.google.code.gson:gson:2.11.0
- net.dv8tion:JDA:${jda.version}
commands:
corechatx:
description: Main CoreChatX command.
aliases: [ ccx ]
usage: /corechatx <reload|settings|locale [tag]|itemcache <warmup|status|cancel>>
msg:
description: Send a private message.
aliases: [ tell, whisper, w ]
usage: /msg <player> <message>
reply:
description: Reply to your last private conversation.
aliases: [ r ]
usage: /reply <message>
socialspy:
description: Toggle private message spy mode.
aliases: [ spy ]
usage: /socialspy
broadcast:
description: Send a formatted staff broadcast.
aliases: [ bc ]
usage: /broadcast <message>
nick:
description: Set or clear a persistent CoreChatX nickname.
usage: /nick <nickname|off>
realname:
description: Resolve a CoreChatX nickname to the player's real Minecraft username.
usage: /realname <nickname>
discord:
description: Link or unlink your Discord account.
usage: /discord <link|unlink|linked|linkadmin>
ping:
description: Manage ping notification preferences.
usage: /ping <sound|actionbar> [on|off|toggle|status]
channel:
description: Manage your active chat channel.
usage: /channel <list|set <id>>
ignore:
description: Ignore a player for private messages.
usage: /ignore <player>
unignore:
description: Remove a player from your ignore list.
usage: /unignore <player>
ignorelist:
description: Show your ignored players.
usage: /ignorelist
pmtoggle:
description: Toggle whether you can receive private messages.
usage: /pmtoggle
chatsettings:
description: Open the CoreChatX settings menu.
aliases: [ ccxsettings ]
usage: /chatsettings
mute:
description: Mute a player temporarily or permanently.
usage: /mute <player> [duration] [reason...]
unmute:
description: Remove a mute from a player.
usage: /unmute <player>
mutechat:
description: Toggle global chat mute.
usage: /mutechat
clearchat:
description: Clear visible chat for online players.
usage: /clearchat
permissions:
corechatx.command.corechatx:
description: Access to the root CoreChatX command.
default: true
corechatx.command.reload:
description: Reload CoreChatX configuration files.
default: op
corechatx.command.settings:
description: Open the CoreChatX settings menu.
default: true
corechatx.command.locale:
description: Change your active CoreChatX locale.
default: true
corechatx.command.itemcache:
description: Warm up and inspect the Discord ChatItem render cache.
default: op
corechatx.command.msg:
description: Send private messages.
default: true
corechatx.command.reply:
description: Reply to private messages.
default: true
corechatx.command.socialspy:
description: Toggle persistent PM spy mode.
default: op
corechatx.command.broadcast:
description: Send global staff broadcasts.
default: op
corechatx.command.nick:
description: Set or clear your own CoreChatX nickname.
default: true
corechatx.command.nick.others:
description: Set or clear another online player's CoreChatX nickname.
default: op
corechatx.command.realname:
description: Resolve a CoreChatX nickname to a real Minecraft username.
default: true
corechatx.command.discord.link:
description: Generate a Discord account link code.
default: true
corechatx.command.discord.unlink:
description: Unlink your Discord account.
default: true
corechatx.command.discord.linked:
description: View your Discord link status.
default: true
corechatx.command.discord.admin:
description: Force or remove Discord account links for other players.
default: op
corechatx.nick.color:
description: Use color codes and safe color tags in CoreChatX nicknames.
default: op
children:
corechatx.nick.color.black: true
corechatx.nick.color.dark-blue: true
corechatx.nick.color.dark-green: true
corechatx.nick.color.dark-aqua: true
corechatx.nick.color.dark-red: true
corechatx.nick.color.dark-purple: true
corechatx.nick.color.gold: true
corechatx.nick.color.gray: true
corechatx.nick.color.dark-gray: true
corechatx.nick.color.blue: true
corechatx.nick.color.green: true
corechatx.nick.color.aqua: true
corechatx.nick.color.red: true
corechatx.nick.color.light-purple: true
corechatx.nick.color.yellow: true
corechatx.nick.color.white: true
corechatx.nick.color.hex: true
corechatx.nick.color.gradient: true
corechatx.nick.color.black:
description: "Use the &0 black color code in CoreChatX nicknames."
default: false
corechatx.nick.color.dark-blue:
description: "Use the &1 dark blue color code in CoreChatX nicknames."
default: false
corechatx.nick.color.dark-green:
description: "Use the &2 dark green color code in CoreChatX nicknames."
default: false
corechatx.nick.color.dark-aqua:
description: "Use the &3 dark aqua color code in CoreChatX nicknames."
default: false
corechatx.nick.color.dark-red:
description: "Use the &4 dark red color code in CoreChatX nicknames."
default: false
corechatx.nick.color.dark-purple:
description: "Use the &5 dark purple color code in CoreChatX nicknames."
default: false
corechatx.nick.color.gold:
description: "Use the &6 gold color code in CoreChatX nicknames."
default: false
corechatx.nick.color.gray:
description: "Use the &7 gray color code in CoreChatX nicknames."
default: false
corechatx.nick.color.dark-gray:
description: "Use the &8 dark gray color code in CoreChatX nicknames."
default: false
corechatx.nick.color.blue:
description: "Use the &9 blue color code in CoreChatX nicknames."
default: false
corechatx.nick.color.green:
description: "Use the &a green color code in CoreChatX nicknames."
default: false
corechatx.nick.color.aqua:
description: "Use the &b aqua color code in CoreChatX nicknames."
default: false
corechatx.nick.color.red:
description: "Use the &c red color code in CoreChatX nicknames."
default: false
corechatx.nick.color.light-purple:
description: "Use the &d light purple color code in CoreChatX nicknames."
default: false
corechatx.nick.color.yellow:
description: "Use the &e yellow color code in CoreChatX nicknames."
default: false
corechatx.nick.color.white:
description: "Use the &f white color code in CoreChatX nicknames."
default: false
corechatx.nick.color.hex:
description: "Use hex color codes like &#ff0000 and <#ff0000> in CoreChatX nicknames."
default: false
corechatx.nick.color.gradient:
description: "Use safe MiniMessage gradient tags in CoreChatX nicknames."
default: false
corechatx.nick.format:
description: Use legacy style codes in CoreChatX nicknames.
default: op
children:
corechatx.nick.format.obfuscated: true
corechatx.nick.format.bold: true
corechatx.nick.format.strikethrough: true
corechatx.nick.format.underline: true
corechatx.nick.format.italic: true
corechatx.nick.format.reset: true
corechatx.nick.format.obfuscated:
description: "Use the &k obfuscated style code in CoreChatX nicknames."
default: false
corechatx.nick.format.bold:
description: "Use the &l bold style code in CoreChatX nicknames."
default: false
corechatx.nick.format.strikethrough:
description: "Use the &m strikethrough style code in CoreChatX nicknames."
default: false
corechatx.nick.format.underline:
description: "Use the &n underline style code in CoreChatX nicknames."
default: false
corechatx.nick.format.italic:
description: "Use the &o italic style code in CoreChatX nicknames."
default: false
corechatx.nick.format.reset:
description: "Use the &r reset style code in CoreChatX nicknames."
default: false
corechatx.command.ping:
description: Change ping notification preferences.
default: true
corechatx.command.channel:
description: Use channel switching commands.
default: true
corechatx.command.ignore:
description: Ignore players for private messages.
default: true
corechatx.command.unignore:
description: Remove ignored players.
default: true
corechatx.command.ignorelist:
description: View your ignore list.
default: true
corechatx.command.pmtoggle:
description: Toggle private message receiving.
default: true
corechatx.command.mute:
description: Mute a player.
default: op
corechatx.command.unmute:
description: Unmute a player.
default: op
corechatx.command.mutechat:
description: Toggle global chat mute.
default: op
corechatx.command.clearchat:
description: Clear visible chat.
default: op
corechatx.moderation.bypass.mutechat:
description: Bypass global chat mute.
default: op
corechatx.moderation.bypass.repeat:
description: Bypass anti-repeat checks.
default: op
corechatx.moderation.bypass.caps:
description: Bypass anti-caps checks.
default: op
corechatx.cooldown.bypass.public:
description: Bypass the public chat cooldown.
default: op
corechatx.cooldown.bypass.pm:
description: Bypass the private message cooldown.
default: op
corechatx.staff:
description: Example shared staff permission used by default custom ping configuration.
default: op
corechatx.chatbubbles.use:
description: Allows the player to use CoreChatX overhead chat bubbles.
default: op
corechatx.chatitem.item:
description: Use [item] and [i] chat item tokens.
default: op
corechatx.chatitem.shulker:
description: Allow [item] to upgrade to a shulker preview when holding a shulker box.
default: op
corechatx.chatitem.armor:
description: Use [armor] chat item tokens.
default: op
corechatx.chatitem.hotbar:
description: Use [hotbar] chat item tokens.
default: op
corechatx.chatitem.inventory:
description: Use [inventory] and [inv] chat item tokens.
default: op
corechatx.chatitem.enderchest:
description: Use [enderchest], [ender], and [ec] chat item tokens.
default: op
corechatx.format.color.black:
description: Use the color code &0 in player-authored messages.
default: op
corechatx.format.color.dark_blue:
description: Use the color code &1 in player-authored messages.
default: op
corechatx.format.color.dark_green:
description: Use the color code &2 in player-authored messages.
default: op
corechatx.format.color.dark_aqua:
description: Use the color code &3 in player-authored messages.
default: op
corechatx.format.color.dark_red:
description: Use the color code &4 in player-authored messages.
default: op
corechatx.format.color.dark_purple:
description: Use the color code &5 in player-authored messages.
default: op
corechatx.format.color.gold:
description: Use the color code &6 in player-authored messages.
default: op
corechatx.format.color.gray:
description: Use the color code &7 in player-authored messages.
default: op
corechatx.format.color.dark_gray:
description: Use the color code &8 in player-authored messages.
default: op
corechatx.format.color.blue:
description: Use the color code &9 in player-authored messages.
default: op
corechatx.format.color.green:
description: Use the color code &a in player-authored messages.
default: op
corechatx.format.color.aqua:
description: Use the color code &b in player-authored messages.
default: op
corechatx.format.color.red:
description: Use the color code &c in player-authored messages.
default: op
corechatx.format.color.light_purple:
description: Use the color code &d in player-authored messages.
default: op
corechatx.format.color.yellow:
description: Use the color code &e in player-authored messages.
default: op
corechatx.format.color.white:
description: Use the color code &f in player-authored messages.
default: op
corechatx.format.style.magic:
description: Use the format code &k in player-authored messages.
default: op
corechatx.format.style.bold:
description: Use the format code &l in player-authored messages.
default: op
corechatx.format.style.strikethrough:
description: Use the format code &m in player-authored messages.
default: op
corechatx.format.style.underline:
description: Use the format code &n in player-authored messages.
default: op
corechatx.format.style.italic:
description: Use the format code &o in player-authored messages.
default: op
corechatx.format.style.reset:
description: Use the format code &r in player-authored messages.
default: op
Velocity Files
The following blocks are the complete bundled Velocity defaults, including comments.
velocity-config.propertiesVelocity group/channel routing, backend group pins, player directory toggles and runtime data notes.
# CoreChatX Velocity proxy settings.
# --- Network groups / channels ---
# Comma-separate values to split this proxy into isolated CoreChatX network groups.
# Each Paper backend joins the group matching its deployment.network-channel.
network-channel=corechatx:main
# Optional backend -> network-channel pins.
# These are required only when Velocity must decide before a backend receives the player,
# such as required Discord link/role login gates in multi-group deployments.
# Keys are Velocity backend names; values must match one value from network-channel.
# backend-groups.survival-1=corechatx:survival
# backend-groups.survival-2=corechatx:survival
# --- Player directory ---
# Adds group player names and @names to client chat completions.
player-directory.chat-completions=true
# Adds group online players to TAB where Velocity exposes them.
player-directory.tab-entries=true
# --- Runtime data storage ---
# In PROXY mode, Velocity is the authority for player settings, nicknames, ignore lists, active channels,
# mutes, global state, Discord links and pending link codes.
# Runtime proxy data is stored separately under data/groups/<encoded-channel>/*.yml.
# Do not place player state, mutes, privacy or Discord links in this config file.
# Discord bot/account-linking settings live in velocity-discord.yml.
# Velocity-owned PROXY join/quit/first-join message formats live in velocity-messages.yml.
velocity-messages.ymlVelocity-owned PROXY join, quit and first-join message formats.
# CoreChatX Velocity messages.
# In PROXY mode, network join/quit/first-join announcements are owned and rendered by Velocity.
# Paper messages.yml is still used for STANDALONE and local-only Paper announcements.
nicknames:
# Prefix inserted directly into {player_nickname} only when a player has a custom nickname.
# Keep this aligned with Paper config.yml -> nicknames.prefix for matching visual output.
prefix: ""
first-join:
# If true, the first accepted proxy/group join uses join-quit.first-join instead of join-quit.join.
enabled: true
# If true, Velocity increments and exposes {count} in the first-join format.
counter-enabled: true
join-quit:
# These switches affect only Velocity-owned PROXY network announcements.
join-enabled: true
quit-enabled: true
# MiniMessage format. Placeholders: {player_name}, {player_nickname}.
# PlaceholderAPI placeholders like %luckperms_prefix% are resolved through PAPIProxyBridge when installed.
join: "<dark_gray>[</dark_gray><green>+</green><dark_gray>]</dark_gray> <white>{player_nickname}</white>"
# MiniMessage format. Placeholders: {player_name}, {player_nickname}.
# PlaceholderAPI placeholders like %luckperms_prefix% are resolved through PAPIProxyBridge when installed.
quit: "<dark_gray>[</dark_gray><red>-</red><dark_gray>]</dark_gray> <white>{player_nickname}</white>"
# MiniMessage format. Placeholders: {player_name}, {player_nickname}, {count}.
# PlaceholderAPI placeholders like %luckperms_prefix% are resolved through PAPIProxyBridge when installed.
first-join: "<dark_gray>[</dark_gray><gradient:#79d6b8:#5aa9ff>Welcome</gradient><dark_gray>]</dark_gray> <white>{player_nickname}</white><gray> is joining for the first time as player </gray><white>#{count}</white><gray>.</gray>"
velocity-discord.ymlVelocity-owned Discord bot, account linking, required-link-to-play, role gates and Discord channel routes.
# CoreChatX Velocity Discord settings.
# In PROXY deployments this is the authority for Discord bridge, account linking and login gates.
# Paper keeps discord.yml for STANDALONE mode and optional per-backend console-only bots.
account-linking:
# Master switch for Discord-Minecraft account linking handled by Velocity.
enabled: false
# If true, linked Discord members get their server nickname synced to their Minecraft nickname.
# Falls back to the Minecraft player name when no custom nickname is set.
sync-mc-name: false
# If true, unlinked Discord users cannot write from Discord into Minecraft bridge channels.
require-linked: false
# Deletes blocked unlinked Discord messages when the bot has Manage Messages in that channel.
delete-unlinked-messages: true
# Sends a private DM explaining why the Discord message was blocked.
dm-unlinked-users: true
# If true, linked Discord users may chat while the Minecraft account is offline when stored data can be resolved.
allow-offline-linked-players: true
# If true, Minecraft mute state blocks linked Discord inbound messages.
enforce-minecraft-mutes: true
# If true, the linked Minecraft account must have permission to send to the target CoreChatX channel.
# Velocity carries this policy to Paper; Paper performs the actual Bukkit/LuckPerms permission check.
enforce-channel-send-permission: true
# If true, unlinked Minecraft players are kicked by backends after Velocity gives them a Discord /link code.
require-linked-to-play: false
required-play-roles:
# Extra login gate for require-linked-to-play. Linked players must have at least one listed Discord role.
enabled: false
# Discord guild/server id used for role checks. If blank and the bot is in one guild, that guild is used automatically.
guild-id: ""
# Discord role ids allowed to join. Empty list disables only the role gate.
role-ids: []
# If true, linked players are denied when Discord role verification cannot be completed.
deny-if-unverifiable: true
# Optional per CoreChatX network-channel overrides.
# Missing fields inherit the global values above. Set enabled: false to disable the role gate for one group.
# Group ids must match velocity-config.properties network-channel values.
groups:
# corechatx:survival:
# enabled: true
# guild-id: ""
# role-ids:
# - "123456789012345678"
# deny-if-unverifiable: true
# corechatx:minigames:
# enabled: true
# role-ids:
# - "234567890123456789"
# Link codes generated by /discord link or required-link-to-play expire after this many minutes.
code-expire-minutes: 10
# Discord slash command names registered by the Velocity bot.
# Change these if another bot/plugin already owns /link or /unlink in the guild.
link-command-name: "link"
unlink-command-name: "unlink"
messages:
unlinked-dm: "Link your Minecraft account before chatting in this channel. Run /discord link in-game, then use the Discord /link command with that code here."
linked: "Your Discord account is now linked to {player_name}."
unlinked: "Your Discord account has been unlinked."
not-linked: "This Discord account is not linked to a Minecraft account."
already-linked: "This Discord account or Minecraft account is already linked. Unlink it first."
code-not-found: "That link code is invalid or expired."
disabled: "CoreChatX Discord account linking is disabled."
unavailable: "CoreChatX cannot complete that Discord linking action right now."
link-required-kick: "<red>You must link your Discord account to play.</red>\n<gray>Use Discord command </gray><white>/link code:{code}</white><gray> within </gray><white>{minutes}</white><gray> minute(s).</gray>"
missing-required-role-kick: "<red>Your Discord account is linked, but you do not have the required Discord role to play.</red>"
role-check-unavailable-kick: "<red>Discord role verification is temporarily unavailable. Try again later.</red>"
discord:
# Starts the Velocity-owned Discord bot for PROXY deployments.
enabled: false
bot-token: ""
default-channel-id: ""
connection-messages:
# If true, accepted proxy-level join, first-join and quit messages are mirrored to Discord once per CoreChatX group.
enabled: false
# Discord channel ids that should receive join/quit mirrors.
# Empty list = discord.default-channel-id.
channels: []
# Tokens: {source}, {source_type}, {source_server}, {channel_id}, {sender_name}, {rank_prefix}, {plain_text}, {message}
format: "{plain_text}"
# Optional action-specific plain-text formats. Leave empty to use format above.
join-format: ""
first-join-format: ""
quit-format: ""
embed:
# If true, join/quit mirrors are sent as a Discord embed instead of plain content.
enabled: false
# Hex color used for the embed side bar.
color: "#57F287"
# Optional action-specific colors. Leave empty to use color above.
join-color: "#57F287"
first-join-color: "#57F287"
quit-color: "#ED4245"
# Leave title empty for a compact embed with only the description.
title: ""
# Supports the same tokens as connection-messages.format.
description: "{plain_text}"
# Optional action-specific descriptions. Leave empty to use description above.
join-description: ""
first-join-description: ""
quit-description: ""
event-messages:
# If true, supported backend server events are mirrored to Discord once per CoreChatX group.
# Supported source_type values for now: death, advancement.
enabled: false
# Discord channel ids that should receive event mirrors.
# Empty list = discord.default-channel-id.
channels: []
# Tokens: {source}, {source_type}, {source_server}, {channel_id}, {sender_name}, {rank_prefix}, {plain_text}, {message}
format: "{plain_text}"
# Optional event-specific plain-text formats. Leave empty to use format above.
death-format: ""
advancement-format: ""
embed:
# Event mirrors are sent as embeds when enabled.
enabled: true
color: "#5865F2"
death-color: "#ED4245"
advancement-color: "#FEE75C"
title: ""
description: "{plain_text}"
death-description: ""
advancement-description: ""
console:
# Allows the Velocity Discord bot to execute proxy console commands from one Discord channel.
# Backend live logs are not mirrored from Velocity; use Paper backend console-only bots for full per-backend live logs.
enabled: false
channel-id: ""
# Set to "" to execute every message in the console channel as a command.
command-prefix: "!"
# Reserved for future proxy log streaming; command responses are returned today.
live-log: false
# Empty allow lists mean anyone who can write in the configured Discord channel can run commands.
allowed-user-ids: []
allowed-role-ids: []
max-response-chars: 1800
player-list:
# PROXY mode player-list command. The Discord channel route selects which CoreChatX network-channel group is listed.
enabled: false
# Text command listened in mapped Discord bridge channels. Set to "" to disable the text command.
command: "!playerlist"
# Also register a slash command. Slash commands can use true ephemeral replies.
register-slash-command: true
slash-command-name: "playerlist"
# CHANNEL = public embed, DM = private DM, EPHEMERAL = slash-only private reply.
# Text commands cannot be ephemeral, so EPHEMERAL falls back to DM for !playerlist.
response-visibility: "CHANNEL"
max-players: 80
embed:
color: "#5865F2"
title: "Online players ({count})"
empty-description: "No players are currently online."
# Tokens: {player_name}, {player_nickname}, {server}.
# PlaceholderAPI placeholders are resolved per listed player through PAPIProxyBridge when installed.
line-format: "- {player_nickname} - {server}"
# Count placeholders: {count}, {shown_count}, {hidden_count}. PAPI placeholders use a player from the listed group when available.
more-format: "... and {hidden_count} more."
channel-description:
# Updates the description/topic of Discord text channels from the Velocity bot.
enabled: false
# Discord rate limits channel metadata updates; keep this at 60 seconds or higher.
interval-seconds: 300
triggers:
# Queue a debounced description update when a player enters a configured CoreChatX group.
on-connection: true
# Queue a debounced description update when a player leaves the proxy.
on-disconnection: true
# Queue a debounced description update when a player moves between CoreChatX groups.
on-group-change: true
# When many players connect/switch/disconnect at once, CoreChatX waits this long after the last event before updating Discord.
event-debounce-seconds: 5
# Each entry updates one Discord text channel description.
# network-channel selects the CoreChatX Velocity group used by {online_in_group}.
# With a single configured group, network-channel can be left blank.
# PlaceholderAPI placeholders like %server_tps% are resolved through PAPIProxyBridge when it is installed on
# Velocity and on the backend servers in this group. If no player is online in the group, only CoreChatX
# internal placeholders can be resolved.
# Internal placeholders:
# {online} = players online on the whole Velocity proxy.
# {online_in_group} = players online inside the selected CoreChatX network-channel group.
entries:
# - channel-id: "123456789012345678"
# network-channel: "corechatx:survival"
# description: "Players {online_in_group}/{online}"
server-status:
# Sends Discord embed messages for proxy startup/shutdown and backend online/offline state changes.
enabled: false
# Velocity pings backend servers listed in velocity-config.properties backend-groups.*.
interval-seconds: 10
offline-threshold: 3
online-threshold: 3
proxy:
enabled: true
# Token value used by {server} for proxy online/offline messages.
id: "velocity"
# Empty channels fall back to default.channels, then discord.default-channel-id.
channels: []
embed:
online:
enabled: true
color: "#57F287"
title: "Proxy online"
description: "`{server}` is now online."
offline:
enabled: true
color: "#ED4245"
title: "Proxy offline"
description: "`{server}` is now offline."
default:
enabled: true
# Discord channel ids. Empty falls back to discord.default-channel-id.
channels: []
embed:
online:
enabled: true
color: "#57F287"
title: "Server online"
description: "`{server}` is now online."
offline:
enabled: true
color: "#ED4245"
title: "Server offline"
description: "`{server}` is now offline."
# Per backend override. Keys must match backend-groups.<server> in velocity-config.properties.
# Any missing field inherits from default; write a custom title/description to avoid showing the technical {server}.
servers:
# survival-1:
# channels:
# - "123456789012345678"
# embed:
# offline:
# color: "#ED4245"
# title: "Survival is offline"
# description: "The main survival backend is not reachable."
# Fallback format used when a backend does not provide a channel-specific Discord template.
# PlaceholderAPI placeholders are resolved through PAPIProxyBridge with the sender UUID when available.
format: "[{source_server}] [{channel_id}] {rank_prefix}{sender_name}: {plain_text}"
# If true, Minecraft -> Discord bridge output breaks Discord mention tokens before sending.
# This prevents players from pinging Discord users, roles, @everyone or @here by typing raw Discord mention syntax in Minecraft.
prevent-mentions-from-minecraft: true
# Optional CoreChatX channel id -> Discord channel id overrides.
# channel-overrides:
# global: "123456789012345678"
channel-overrides: {}
inbound:
enabled: false
default-channel: "global"
max-length: 400
# Map Discord channel ids to CoreChatX channel ids.
# With one network-channel group, a simple string value is enough:
# channel-routes:
# "123456789012345678": "global"
#
# With multiple Velocity network-channel groups, use object values and select the target group:
# channel-routes:
# "123456789012345678":
# channel: "global"
# network-channel: "corechatx:survival"
# require-linked: inherit
channel-routes: {}
# Optional per Discord route account-link override.
# Values: inherit, true, false.
route-overrides: {}
velocity-plugin.jsonVelocity plugin metadata.
{
"id": "corechatx",
"name": "CoreChatX",
"version": "${project.version}",
"description": "Proxy-side foundation module for optional CoreChatX network mode.",
"authors": [
"IceWolf23X"
],
"main": "me.icewolf23.corechatx.velocity.bootstrap.CoreChatXVelocityPlugin",
"dependencies": [
{
"id": "papiproxybridge",
"optional": true
}
]
}
Troubleshooting
- Mixed Paper/Velocity builds: update both jars together. The plugin-message protocol is internal and mixed versions are not supported.
- Unlinked kick on a proxy network: verify Velocity is installed,
network-channelvalues match andvelocity-discord.ymlhas account linking enabled. - Role check fails: verify the Velocity bot is online,
guild-idis correct or unambiguous, role IDs are numeric Discord role IDs and the bot can retrieve guild members. - Discord messages route to the wrong group: use object routes in
discord.inbound.channel-routesand include the targetnetwork-channel. - Config changes do not apply: identity settings such as
deployment.mode,deployment.server-id,deployment.network-channeland Velocitynetwork-channelrequire restart.