Rules Engine
Overview
The rules engine processes chat messages, commands, signs, books, anvils, and tags through regex-based rules. Each rule has a match pattern, optional conditions (require/ignore), and action handlers (then). Rules are defined in .rs files under rules/. Reusable operator sets are called "groups" (defined in groups.rs).
Architecture
Key Classes
- •
Rule(operator/Rule.java) — individual rule with regex pattern, extendsRuleOperator - •
RuleOperator(operator/RuleOperator.java) — base providing require/ignore conditions and replace/rewrite actions - •
Operator(operator/Operator.java) — universal base for all operators (timing, actions, data persistence) - •
Rules(operator/Rules.java) — singleton loader/registry for all rules - •
Group(operator/Group.java) — reusable operator set referenced bygroup <name> - •
Groups(operator/Groups.java) — singleton loader for groups fromgroups.rs - •
RuleType(core: model/RuleType.java) — enum: GLOBAL, CHAT, COMMAND, SIGN, BOOK, ANVIL, TAG
Rule Processing Flow
code
Message/command/sign/book/anvil/tag input
→ Rules.getRules(type) loads rules for this type
→ For each rule (top to bottom):
1. @import: imported rules checked first
2. Compile matcher (apply strip colors/accents if set)
3. Match regex against message
4. If match: fire PreRuleMatchEvent (API — cancellable)
5. Check require/ignore conditions (canFilter())
6. Execute rule operators (executeOperators())
7. Execute group operators if `group <name>` set
8. If `then abort`: stop processing remaining rules
Common Issues & Solutions
"Rule isn't matching"
- •Enable
Rules.Verbose: truein settings.yml for match logs - •Test regex at regex101.com (use Java/PCRE flavor)
- •Check
Rules.Apply_Onincludes the type - •Verify
strip colorsisn't removing needed characters - •Check rule order — earlier rules with
then abortmay stop processing - •Check
ignore stringisn't excluding the input
"Group operators not executing"
- •Verify group name exists in
groups.rs(case-sensitive) - •Group operators execute AFTER rule-level operators
- •Groups cannot reference other groups (no nesting)
- •Groups don't support
ignore typeoperator
"Replace not working correctly"
- •
then replacereplaces the MATCHED portion only, not full message - •
then rewritereplaces the ENTIRE message - •
@prolong *creates asterisks matching the matched text length - •Replacements happen in rule order (later rules see modified text)
"JavaScript condition errors"
- •Scripts see fully variable-replaced text, logged on error for debugging
- •Must return boolean (
true/false) - •Player context:
{player}object available
"Rules applying to Discord messages"
- •Add
ignore discordto rules that shouldn't affect Discord input - •Use
require discordfor Discord-only rules
Key File Paths
- •Rule class:
chatcontrol-bukkit/src/main/java/org/mineacademy/chatcontrol/operator/Rule.java - •Operator base:
chatcontrol-bukkit/src/main/java/org/mineacademy/chatcontrol/operator/Operator.java - •Rules manager:
chatcontrol-bukkit/src/main/java/org/mineacademy/chatcontrol/operator/Rules.java - •Groups:
chatcontrol-bukkit/src/main/java/org/mineacademy/chatcontrol/operator/Groups.java - •Rule files:
chatcontrol-bukkit/src/main/resources/rules/ - •Foundation RuleSetReader:
foundation-core/src/main/java/org/mineacademy/fo/model/RuleSetReader.java
Reference
For configuration keys, default values, commands, permissions, and variables not covered above, read the source files directly using read_codebase_file. The key file paths above point to the most relevant files.