JP Plugins
All plugins

JPChat

Chat formatting, moderation and private messaging for Paper servers.

Display plugin, version 1.0.0

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

  1. Put JPChat-<version>.jar in your server's plugins folder.
  2. Restart the server. plugins/JPChat/ is created with the config and messages.
  3. 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

CommandDescriptionPermission
/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
/msgtoggle
Aliases: /togglemsg, /tpm
Toggle receiving private messages.jpchat.msg.toggle
/ignore <player|list>
Aliases: /unignore
Ignore or unignore a player.jpchat.ignore
/socialspy
Aliases: /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

PermissionDefaultDescription
jpchat.*operatorsEvery JPChat permission.
jpchat.adminoperatorsReload JPChat and trigger announcements.
jpchat.namecoloreveryoneOpen /namecolor (each colour needs its own jpchat.namecolor.<colour>).
jpchat.chatgames.playeveryoneTake part in chat games.
jpchat.chatgames.adminoperatorsStart and stop chat games with /chatgame.
jpchat.msgeveryoneSend private messages.
jpchat.msg.toggleeveryoneToggle private messages.
jpchat.ignoreeveryoneIgnore players.
jpchat.emojieveryoneUse emoji shortcuts.
jpchat.itemeveryoneShow items with [item].
jpchat.linkeveryoneSend clickable links.
jpchat.socialspyoperatorsSee other players' private messages.
jpchat.broadcastoperatorsBroadcast messages.
jpchat.notifyoperatorsSee filtered message alerts.
jpchat.coloroperatorsUse &0-&f colours in chat.
jpchat.styleoperatorsUse &l &o &n &m &k in chat.
jpchat.hexoperatorsUse &#RRGGBB colours in chat.
jpchat.minimessageoperatorsUse MiniMessage tags in chat.
jpchat.bypass.cooldownoperatorsBypass the chat cooldown and anti-spam.
jpchat.bypass.filteroperatorsBypass word, caps and advertising filters.
jpchat.bypass.ignoreoperatorsCannot be ignored.
jpchat.bypass.msgtoggleoperatorsMessage players who disabled private messages.
jpchat.mention.everyoneoperatorsPing everyone with @everyone.
jpchat.announcer.hidenobodyDo not receive automatic announcements.
jpchat.format.vipnobodyUse the vip chat format.
jpchat.format.staffnobodyUse the staff chat format.

Placeholders

Needs PlaceholderAPI.

PlaceholderShows
%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: '&#5EA1FF&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[&#7ED957+&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[&#7ED957+&8] &7{name} &8({server})'
  quit-format: '&8[&#FF5F6D-&8] &7{name} &8({server})'

Support

Guides and the docs of every JP plugin are on the JP Plugins website. 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.