JPChat
Chat formatting, moderation and private messaging for Paper servers.
Downloads open soon.
Features
- Chat formats per rank (Vault/LuckPerms), with MiniMessage and hex colours
- Private messages, replies, ignore, social spy and message toggle
- Name colours players pick themselves (
/namecolor) - Mentions, item showcase and emojis
- Anti-spam, anti-caps, anti-advertising and a word filter
- Local chat, join and quit messages, broadcasts and an announcer
- Chat games with rewards
- Cross-server chat over MySQL or Redis
Requirements
- Paper 26.1 or newer (Java 25)
- Optional:
- Vault: ranks, and money for chat game rewards
- PlaceholderAPI: placeholders in texts, and this plugin's own placeholders
- LuckPerms: ranks, prefixes and suffixes
- JPStaff: mutes, vanish and staff data
Installation
- Put
JPChat-<version>.jarin your server'spluginsfolder. - Restart the server.
plugins/JPChat/is created with the config and messages. - Change what you want in the files, then reload or restart.
Type /jp as an operator to see every JP plugin you have installed, its version and which optional plugins it found.
Commands
| Command | Description | Permission |
|---|---|---|
/jpchat <reload|announce> | JPChat admin command. | jpchat.admin |
/msg <player> <message>Aliases: /tell, /w, /whisper, /m, /pm, /message | Send a private message. | jpchat.msg |
/r <message>Aliases: /r | Reply to your last private message. | jpchat.msg |
/msgtoggleAliases: /togglemsg, /tpm | Toggle receiving private messages. | jpchat.msg.toggle |
/ignore <player|list>Aliases: /unignore | Ignore or unignore a player. | jpchat.ignore |
/socialspyAliases: /spy | Toggle social spy. | jpchat.socialspy |
/broadcast <message>Aliases: /bc, /bcast | Broadcast a message to everyone. | jpchat.broadcast |
/namecolor [colour|reset]Aliases: /nc, /namecolour, /chatcolor | Pick the colour of your name in chat. | jpchat.namecolor |
/chatgame <start [type]|stop>Aliases: /chatgames | Start or stop a chat game. | jpchat.chatgames.admin |
Permissions
| Permission | Default | Description |
|---|---|---|
jpchat.* | operators | Every JPChat permission. |
jpchat.admin | operators | Reload JPChat and trigger announcements. |
jpchat.namecolor | everyone | Open /namecolor (each colour needs its own jpchat.namecolor.<colour>). |
jpchat.chatgames.play | everyone | Take part in chat games. |
jpchat.chatgames.admin | operators | Start and stop chat games with /chatgame. |
jpchat.msg | everyone | Send private messages. |
jpchat.msg.toggle | everyone | Toggle private messages. |
jpchat.ignore | everyone | Ignore players. |
jpchat.emoji | everyone | Use emoji shortcuts. |
jpchat.item | everyone | Show items with [item]. |
jpchat.link | everyone | Send clickable links. |
jpchat.socialspy | operators | See other players' private messages. |
jpchat.broadcast | operators | Broadcast messages. |
jpchat.notify | operators | See filtered message alerts. |
jpchat.color | operators | Use &0-&f colours in chat. |
jpchat.style | operators | Use &l &o &n &m &k in chat. |
jpchat.hex | operators | Use &#RRGGBB colours in chat. |
jpchat.minimessage | operators | Use MiniMessage tags in chat. |
jpchat.bypass.cooldown | operators | Bypass the chat cooldown and anti-spam. |
jpchat.bypass.filter | operators | Bypass word, caps and advertising filters. |
jpchat.bypass.ignore | operators | Cannot be ignored. |
jpchat.bypass.msgtoggle | operators | Message players who disabled private messages. |
jpchat.mention.everyone | operators | Ping everyone with @everyone. |
jpchat.announcer.hide | nobody | Do not receive automatic announcements. |
jpchat.format.vip | nobody | Use the vip chat format. |
jpchat.format.staff | nobody | Use the staff chat format. |
Placeholders
Needs PlaceholderAPI.
| Placeholder | Shows |
|---|---|
%jpchat_name% | the player's name in their /namecolor colour |
%jpchat_namecolor% | key of the chosen colour ("" = default) |
%jpchat_msgtoggle% | true when they accept private messages |
%jpchat_socialspy% | true when social spy is on |
Configuration
All files are in plugins/JPChat/. Files: config.yml, messages.yml.
When you update the plugin, new options are added to your config.yml by themselves, with their comments. Your own settings stay as they are, and the old file is kept as config.old-v<number>.yml.
Languages: English, Spanish, Portuguese, French and German. Set language: in config.yml (en, es, pt, fr or de).
Default config.yml
# Used to add new options to this file after an update. Don't change it.
config-version: 1
# ==========================================================
# JPChat - chat formatting, moderation & private messages
# ==========================================================
# Every text option accepts legacy codes (&a, &l, &#FF8800) AND MiniMessage
# tags (<gradient:#ff8800:#ffd000>, <hover:show_text:'...'>, <click:...>).
# PlaceholderAPI placeholders (%vault_rank%, %player_level%...) work everywhere
# when PlaceholderAPI is installed.
#
# Apply changes with /jpchat reload. Texts for commands live in messages.yml.
# Sounds use Bukkit names (BLOCK_NOTE_BLOCK_PLING...).
#
# What players may type in chat is controlled by permissions (default: op only):
# jpchat.color every colour code (&0-&9, &a-&f)
# jpchat.color.<code> one colour only, e.g. jpchat.color.c (red), jpchat.color.6 (gold)
# jpchat.style every format code (&k &l &m &n &o)
# jpchat.style.<code> one format only, e.g. jpchat.style.l (bold)
# jpchat.hex &#RRGGBB colours
# jpchat.minimessage MiniMessage tags (<gradient>, <rainbow>...)
# Give them to ranks in LuckPerms, e.g. /lp group vip permission set jpchat.color.6
# Language of the messages: en (messages.yml), es, pt, fr or de (lang/<code>.yml).
# Your own language: copy a file in the lang folder to lang/<code>.yml, translate it
# and set its code here (for example it for lang/it.yml).
language: en
# Replace messages.yml with the new design when the plugin is updated.
# Your old file is kept as messages.old-vX.yml. false = never touch it.
auto-update-style: true
# ----------------------------------------------------------
# Modules - switch whole features on or off
# ----------------------------------------------------------
modules:
# Replace the vanilla "<name> message" format with the formats below.
chat-format: true
# Hover card and click action on player names in chat.
name-hover: true
name-click: true
# /ignore <player>
ignore: true
# /socialspy - staff see private messages (jpchat.socialspy)
social-spy: true
# /broadcast <message>
broadcast: true
# /msgtoggle - players can turn off incoming private messages
msg-toggle: true
# ----------------------------------------------------------
# Chat formats
# ----------------------------------------------------------
# The format with the highest priority that the player has access to is used.
# Access is granted by "permission" (leave empty for everyone) or by matching
# the player's primary Vault group with "group".
#
# Placeholders: {prefix} {suffix} {name} {displayname} {world} {group} {message}
# {prefix}/{suffix} come from Vault (e.g. LuckPerms prefixes).
# {name} is coloured by the player's name colour (see "name-colors" below), so do not
# put a colour right before it.
#
# Add your own like this (any name works):
# builder:
# priority: 20
# group: 'builder' # players whose primary group is "builder"
# format: '{prefix}&a{name} &8» &f{message}'
formats:
default:
priority: 0
permission: ''
format: '{prefix}{name} &8» &7{message}'
vip:
priority: 10
permission: 'jpchat.format.vip'
format: '{prefix}{name} &8» &f{message}'
staff:
priority: 100
permission: 'jpchat.format.staff'
format: '{prefix}{name} &8» &f{message}'
name:
# Lines shown when hovering a player's name in chat.
hover:
- '<gradient:#EE9CA7:#FFDDE1><bold>{name}</bold></gradient>'
- '&8▪ &7Rank &f{group}'
- '&8▪ &7World &f{world}'
- ''
- '&#FFD27F➜ &7Click to message'
# Clicking a name: suggest = fills the chat box, run = runs the command.
# {name} = the clicked player.
click-action: suggest
click-command: '/msg {name} '
# ----------------------------------------------------------
# Name colours (/namecolor)
# ----------------------------------------------------------
# Every name is white and not bold unless the player picks a colour with /namecolor
# (a menu, or /namecolor <colour>). Each colour needs its permission, so you decide
# which ranks unlock which colours, e.g.
# /lp group vip permission set jpchat.namecolor.gold
# The menu shows every colour; locked ones say which permission they need.
name-colors:
enabled: true
# Style used when the player has not picked a colour. {name} = the player's name.
default: '&f{name}'
# Show colours the player has not unlocked yet (greyed out).
show-locked: true
# key: used in /namecolor <key> and the default permission jpchat.namecolor.<key>
# name: shown in the menu
# style: colours around {name}; MiniMessage gradients work too
# icon: item in the menu
# permission: optional, defaults to jpchat.namecolor.<key> ('' = everyone)
colors:
white:
name: '&fWhite'
style: '&f{name}'
icon: WHITE_WOOL
permission: ''
gray:
name: '&7Gray'
style: '&7{name}'
icon: LIGHT_GRAY_WOOL
yellow:
name: '&eYellow'
style: '&e{name}'
icon: YELLOW_WOOL
gold:
name: '&6Gold'
style: '&6{name}'
icon: ORANGE_WOOL
green:
name: '&aGreen'
style: '&a{name}'
icon: LIME_WOOL
aqua:
name: '&bAqua'
style: '&b{name}'
icon: LIGHT_BLUE_WOOL
blue:
name: '&9Blue'
style: '&9{name}'
icon: BLUE_WOOL
pink:
name: '&dPink'
style: '&d{name}'
icon: PINK_WOOL
red:
name: '&cRed'
style: '&c{name}'
icon: RED_WOOL
purple:
name: '&5Purple'
style: '&5{name}'
icon: PURPLE_WOOL
sunset:
name: '<gradient:#FF416C:#FFD27F>Sunset</gradient>'
style: '<gradient:#FF416C:#FFD27F>{name}</gradient>'
icon: ORANGE_TERRACOTTA
ocean:
name: '<gradient:#2193B0:#6DD5ED>Ocean</gradient>'
style: '<gradient:#2193B0:#6DD5ED>{name}</gradient>'
icon: CYAN_TERRACOTTA
candy:
name: '<gradient:#EE9CA7:#B784FF>Candy</gradient>'
style: '<gradient:#EE9CA7:#B784FF>{name}</gradient>'
icon: PINK_TERRACOTTA
rainbow:
name: '<rainbow>Rainbow</rainbow>'
style: '<rainbow>{name}</rainbow>'
icon: NETHER_STAR
# ----------------------------------------------------------
# Message features
# ----------------------------------------------------------
features:
# Turn http(s) links into clickable text (players need jpchat.link).
clickable-links: true
link-format: 'EA1FF&n{url}'
link-hover: '&7Click to open &f{url}'
# Highlight and ping players whose name appears in a message (with or without @).
mentions:
enabled: true
format: '&#FFD000@{name}'
sound: ENTITY_EXPERIENCE_ORB_PICKUP
actionbar: '&#FFD000{sender} &7mentioned you in chat'
# Players need jpchat.mention.everyone to ping @everyone.
everyone-keyword: '@everyone'
# [item] / [i] shows the item held in the main hand with a hover preview (jpchat.item).
item-showcase:
enabled: true
keywords: ['[item]', '[i]']
format: '&8[&f{item}&7 x{amount}&8]'
# Simple text replacements. Players need jpchat.emoji.
emojis:
enabled: true
replacements:
':heart:': '<red>❤</red>'
':star:': '<yellow>★</yellow>'
':check:': '<green>✔</green>'
':x:': '<red>✘</red>'
':arrow:': '➜'
':shrug:': '¯\_(ツ)_/¯'
':skull:': '☠'
':music:': '♫'
# ----------------------------------------------------------
# Local chat (optional)
# ----------------------------------------------------------
# When enabled, messages are only seen by players in the same world within the
# radius. Start a message with the global prefix to talk to everyone.
local-chat:
enabled: false
# Blocks around the sender.
radius: 100
# "!hello" goes to everyone.
global-prefix: '!'
# Put in front of global and local messages.
global-tag: '&8[&6G&8] '
local-tag: '&8[&7L&8] '
# ----------------------------------------------------------
# Moderation
# ----------------------------------------------------------
# Staff with jpchat.bypass.filter skip the word, caps and advertising filters;
# jpchat.bypass.cooldown skips the cooldown and anti-spam.
moderation:
# Seconds between chat messages. Bypass: jpchat.bypass.cooldown
cooldown-enabled: true
cooldown-seconds: 1.5
anti-spam:
enabled: true
# Block messages that are this similar (0.0-1.0) to the previous one...
similarity-threshold: 0.85
# ...if sent within this many seconds.
window-seconds: 20
anti-caps:
enabled: true
# Shorter messages are never touched ("OK", "LOL"...).
min-length: 8
# Messages with more uppercase letters than this percentage are lowercased.
max-percentage: 60
anti-advertising:
enabled: true
# block = cancel the message, censor = replace the address with ***
mode: block
# Addresses that are always allowed.
whitelist:
- 'youtube.com'
- 'youtu.be'
- 'imgur.com'
- 'discord.gg/yourserver'
word-filter:
enabled: true
# censor = replace the word with the censor character, block = cancel the message
mode: censor
censor-character: '*'
# Plain words match whole words in any case. Prefix with "regex:" for a pattern.
words:
- 'badword'
- 'regex:f+u+c+k+'
# Staff with jpchat.notify see blocked/censored messages.
notify-staff: true
# ----------------------------------------------------------
# Private messages
# ----------------------------------------------------------
# /msg <player> <message> and /r <message>.
# Placeholders: {sender} {target} {message}, and PlaceholderAPI ones (filled for the sender)
private-messages:
enabled: true
format-sent: '&#EE9CA7✉ &8[&7me &8➜ &f{target}&8] &7{message}'
format-received: '&#EE9CA7✉ &8[&f{sender} &8➜ &7me&8] &f{message}'
format-spy: '&8[&#FF5F6DSpy&8] &7{sender} &8➜ &7{target}&8: &f{message}'
# Played to the receiver.
sound: BLOCK_NOTE_BLOCK_PLING
# Apply the moderation filters (word filter, advertising) to private messages too.
apply-filters: true
# ----------------------------------------------------------
# Join & quit messages
# ----------------------------------------------------------
# Vanished players (JPStaff, SuperVanish, PremiumVanish...) never trigger these.
# Placeholders: {name} everywhere, {count} in first-join (number of players who ever
# joined), {online} in motd (players online).
# Set a message to '' to hide it.
join-quit:
enabled: true
join: '&8[ED957+&8] &7{name}'
quit: '&8[&#FF5F6D-&8] &7{name}'
first-join: '<gradient:#EE9CA7:#FFDDE1>✦</gradient> &fWelcome &#EE9CA7{name} &fto the server! &8(#{count})'
# Message shown only to the joining player.
motd-enabled: true
motd:
- ''
- ' <gradient:#EE9CA7:#FFDDE1><bold>Welcome back, {name}!</bold></gradient>'
- ' &7There are &f{online} &7players online.'
- ''
# ----------------------------------------------------------
# Broadcasts & announcer
# ----------------------------------------------------------
# /broadcast <message> (jpchat.broadcast).
broadcast:
format: '<gradient:#FF416C:#FF4B2B><bold>ʙʀᴏᴀᴅᴄᴀꜱᴛ</bold></gradient> &8» &f{message}'
sound: BLOCK_NOTE_BLOCK_BELL
# Automatic messages sent to everyone. Each entry under "messages" is one
# announcement (several lines). Send one now with /jpchat announce [name].
announcer:
enabled: true
# Seconds between announcements.
interval-seconds: 300
# false = in order, true = random order.
random: false
sound: BLOCK_NOTE_BLOCK_CHIME
# Players with jpchat.announcer.hide do not receive announcements.
messages:
tips:
- ''
- ' <gradient:#EE9CA7:#FFDDE1><bold>ᴛɪᴘ</bold></gradient> &8» &7Use &f/msg <player> <message> &7to chat privately.'
- ''
rules:
- ''
- ' <gradient:#FF416C:#FF4B2B><bold>ʀᴜʟᴇꜱ</bold></gradient> &8» &7Be respectful and have fun!'
- ' &7Read the full rules with &f/rules&7.'
- ''
# ----------------------------------------------------------
# Chat games
# ----------------------------------------------------------
# Every few minutes a small challenge appears in chat. The first player to type the
# answer wins. Staff can start one now with /chatgame start [type] (jpchat.chatgames.admin).
# Players need jpchat.chatgames.play to take part (everyone has it by default).
chat-games:
enabled: true
# Seconds between games.
interval-seconds: 600
# Only start games when at least this many players are online.
min-players: 2
# Seconds players get to answer.
answer-seconds: 45
# true = the winning answer is not shown in chat (others cannot copy it).
hide-winning-message: false
# Games to pick from at random:
# unscramble "rpetimaun" -> minecraft type type the word as fast as you can
# reverse "tfarcenim" -> minecraft math small sums (12 + 7, 9 × 4...)
# trivia questions from the list below
types: [unscramble, type, reverse, math, trivia]
# Highest number used in math games.
math-max-number: 20
rewards:
# Money for the winner (needs Vault and an economy plugin). 0 = none.
money: 100
# Console commands for the winner. {player} = the winner's name.
commands: []
sounds:
start: BLOCK_NOTE_BLOCK_BELL
win: UI_TOAST_CHALLENGE_COMPLETE
# Words for unscramble, type and reverse games.
words: [minecraft, diamond, creeper, emerald, redstone, enderman, obsidian, netherite,
villager, skeleton, pickaxe, beacon, elytra, trident, lantern, furnace, cobblestone,
enchantment, strider, axolotl, sniffer, amethyst, campfire, shulker, phantom]
# Trivia questions. answers: every accepted answer (not case-sensitive).
trivia:
- question: 'How many blocks of obsidian does the smallest Nether portal need?'
answers: ['10', 'ten']
- question: 'Which mob drops blaze rods?'
answers: ['blaze', 'a blaze', 'blazes']
- question: 'What do you need to tame a wolf?'
answers: ['bone', 'bones', 'a bone']
- question: 'Which ore is found only in the Nether and gives netherite scrap?'
answers: ['ancient debris', 'debris']
- question: 'How many slots are in a double chest?'
answers: ['54', 'fifty four', 'fifty-four']
- question: 'Which boss drops a nether star?'
answers: ['wither', 'the wither']
- question: 'What item do you use to breed cows?'
answers: ['wheat']
- question: 'At which Y level is bedrock at the bottom of the overworld?'
answers: ['-64']
# Hook into PlaceholderAPI and Vault when available.
hooks:
placeholderapi: true
vault: true
# ----------------------------------------------------------
# Network (several servers behind Velocity or BungeeCord)
# ----------------------------------------------------------
# Chat, /broadcast and private messages reach players on the other servers too.
# Every server needs the same settings here (except server-name).
# MYSQL = through a MySQL database all servers can reach (fill in "mysql" below).
# No extra software; messages arrive within about a second.
# REDIS = through a Redis server: instant. Fill in "redis" below.
network:
enabled: false
# A short name for this server, shown in front of chat from it: [lobby] Steve > hi
server-name: 'lobby'
messenger: MYSQL
mysql:
host: localhost
port: 3306
database: minecraft
username: root
password: change-me
parameters: useSSL=false&characterEncoding=utf8
# How often the MySQL messenger looks for new messages, in milliseconds.
mysql-poll-ms: 1000
redis:
host: localhost
port: 6379
password: ''
channel: jp
# What to share. Local chat (local-chat) always stays on its own server.
chat: true
broadcasts: true
private-messages: true
# Put in front of chat from other servers. {server} = its server-name.
server-prefix: '&8[&7{server}&8] '
# Tell the whole network when someone joins/leaves a server (JPChat's own join
# messages still show on the server itself).
join-messages: false
join-format: '&8[ED957+&8] &7{name} &8({server})'
quit-format: '&8[&#FF5F6D-&8] &7{name} &8({server})'Support
Questions, bugs or ideas? Join the JP Plugins Discord.
License
JPChat is free to use on any server, including servers that make money, but it is not open source. Don't reupload, sell or share modified copies of it. The full terms are in LICENSE.txt, which is also inside the jar.