AgentSkillsCN

messages

ChatControl 消息广播:支持加入/退出/踢人/死亡/定时消息,.rs 消息文件,条件判断(要求/忽略发送者/接收者),消息分组、格式化设置、随机消息与顺序消息,以及代理广播功能。当您需要配置加入/退出/死亡/定时消息,或排查广播相关问题时,可使用此功能。

SKILL.md
--- frontmatter
name: messages
description: 'ChatControl message broadcasting: join/quit/kick/death/timed messages, .rs message files, conditions (require/ignore sender/receiver), message groups, formats, random/sequential messages, proxy broadcasting. Use when configuring join/quit/death/timed messages or diagnosing broadcast issues.'

Message Broadcasting System

Overview

ChatControl replaces vanilla join/quit/kick/death messages and adds scheduled timed broadcasts. Messages are defined in .rs files under messages/ with conditional logic, formatting, and proxy support.

Architecture

Key Classes

  • PlayerMessage (operator/PlayerMessage.java) — abstract base for all message types
  • PlayerMessages (operator/PlayerMessages.java) — singleton loader and broadcaster
  • JoinQuitKickMessage (operator/JoinQuitKickMessage.java) — wrapper for join/quit/kick
  • DeathMessage (operator/DeathMessage.java) — death-specific conditions (killer, cause, etc.)
  • TimedMessage (operator/TimedMessage.java) — scheduled broadcast with delay
  • PlayerMessageType (core: model/PlayerMessageType.java) — enum: JOIN, QUIT, KICK, DEATH, TIMED

Broadcast Flow

code
Event triggers (join/quit/death/timer)
  → PlayerMessages.broadcast(type, wrapped, message)
    → For each message group (top to bottom):
      1. Check sender conditions (require/ignore sender perm/script/world/etc.)
      2. Check timing (begins/expires/delay)
      3. Select message text (random or sequential)
      4. Build format using Format.parse()
      5. For each receiver: check receiver conditions
      6. Send formatted component
      7. Fire PlayerMessageEvent (API)
      8. If Settings.Messages.STOP_ON_FIRST_MATCH: stop after first match

Message File Syntax (.rs)

Basic Structure

code
group first_join
require sender script {statistic_PLAY_ONE_MINUTE} == 0
message:
- Welcome {player} to the server!
- First time here? Type /help

group default_join
message:
- {player} joined the game

Message-Specific Operators

Messages:

code
group <name>           — unique group identifier
message:               — message list (following lines indented with space)
- Line 1               — individual messages (random or sequential)
- Line 2
prefix <text>          — prepend to every message
suffix <text>          — append to every message
random true            — random selection (default: false = sequential)
proxy true             — broadcast to proxy network

Sender Conditions:

code
require sender perm <permission>
require sender script <javascript>
require sender variable <var> <value>
require sender gamemode <mode>
require sender world <world>
require sender region <region>
require sender channel <channel> [mode]
require self                     — only show to the sender

Receiver Conditions:

code
require receiver perm <permission>
require receiver script <javascript>
require receiver variable <var> <value>
require receiver gamemode <mode>
require receiver world <world>
require receiver region <region>
require receiver channel <channel> [mode]
ignore self                      — don't show to the sender

Ignore variants: Same structure with ignore prefix.

Death Message Extra Operators

code
require cause <DamageCause>      — FALL, DROWNING, ENTITY_ATTACK, etc.
require projectile <EntityType>  — ARROW, TRIDENT, etc.
require block <Material>         — falling block type
require killer <EntityType>      — killer entity type
require boss <name>              — Boss/MythicMobs boss name
require damage <number>          — minimum damage taken
require npc / ignore npc         — Citizens NPC check

require killer perm <perm>       — killer-specific conditions
require killer script <js>
require killer world <world>
require killer item <material>   — killer's held item (supports wildcards: *_SWORD)

Death Variables:

  • {killer}, {killer_name}, {killer_type} — killer info
  • {killer_item}, {killer_item_name} — killer weapon
  • {block_type}, {cause}, {projectile} — death details
  • {boss_name} — boss name (if applicable)

All Operators from Operator Base

Messages support all base operators: then command, then console, then sound, then title, then actionbar, then bossbar, then toast, delay, begins, expires, etc.

Configuration (settings.ymlMessages)

KeyDefaultPurpose
Apply_On[join, quit, kick, death, timed]Which types are enabled
Stop_On_First_MatchtrueStop after first matching group
Timed_Delay3 minutesDelay between timed broadcasts
Prefix.Join / .Quit / etc.format stringsDefault message prefix per type

Message Files

FileTypePurpose
messages/join.rsJOINJoin messages
messages/quit.rsQUITQuit messages
messages/kick.rsKICKKick messages
messages/death.rsDEATHDeath messages
messages/timed.rsTIMEDScheduled broadcasts

Timed Messages

Timed messages run on a global timer (Settings.Messages.TIMED_DELAY). Each group can override with its own delay:

code
group tips
delay 5 minutes
message:
- Tip: Use /help for commands
- Tip: Join our Discord at discord.gg/example

group world_specific
require sender world hardcore
delay 10 minutes
message:
- Hardcore tip: Sleep sets your respawn point

Common Issues & Solutions

"Join/quit messages not showing"

  1. Check Messages.Apply_On contains join/quit
  2. Verify no other plugin cancels the event
  3. Check Stop_On_First_Match — first match stops all further groups
  4. Ensure message group order: most specific on top

"First-join detection not working"

  • Use require sender script {statistic_PLAY_ONE_MINUTE} == 0
  • MC 1.13+: PLAY_ONE_MINUTE (misleading name — counts in ticks)
  • MC 1.7-1.12: PLAY_ONE_TICK
  • Place first-join group ABOVE default join (Stop_On_First_Match)

"Death message shows wrong format"

  1. Check require cause matches the death type
  2. Entity names changed in MC 1.20.5+ (LIGHTNING_BOLT, TNT, END_CRYSTAL)
  3. Killer item supports wildcards (*_SWORD, DIAMOND_*)
  4. {killer} is null for environmental deaths — check for it

"Timed messages not cycling"

  • Default is sequential (not random). Use random true for random.
  • delay per-group overrides global Timed_Delay
  • Timed messages skip first run after reload (prevents spam)
  • Timer resets on /chc reload

"Message shows to wrong players"

  • Use require receiver world/perm/script to filter recipients
  • require self / ignore self controls self-visibility
  • Channel conditions restrict to channel members

Key File Paths

  • PlayerMessage: chatcontrol-bukkit/src/main/java/org/mineacademy/chatcontrol/operator/PlayerMessage.java
  • PlayerMessages: chatcontrol-bukkit/src/main/java/org/mineacademy/chatcontrol/operator/PlayerMessages.java
  • DeathMessage: chatcontrol-bukkit/src/main/java/org/mineacademy/chatcontrol/operator/DeathMessage.java
  • TimedMessage: chatcontrol-bukkit/src/main/java/org/mineacademy/chatcontrol/operator/TimedMessage.java
  • Message files: chatcontrol-bukkit/src/main/resources/messages/
  • Settings: chatcontrol-bukkit/src/main/resources/settings.yml (Messages section)

API Events

  • PlayerMessageEvent — fired for all message broadcasts (cancellable)

Foundation Integration

  • RuleSetReader — parses .rs file format
  • Operator — base class providing timing, commands, and visual actions
  • SimpleComponent — builds formatted output
  • Format — resolves format references