-
-
Notifications
You must be signed in to change notification settings - Fork 9
GH-148 Implement mentions system with @player detection and sound notifications #208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Co-authored-by: Jakubk15 <[email protected]>
Co-authored-by: Jakubk15 <[email protected]>
Co-authored-by: Jakubk15 <[email protected]>
Co-authored-by: Jakubk15 <[email protected]>
# Conflicts: # build.gradle.kts # buildSrc/build.gradle.kts # chatformatter-paper-plugin/build.gradle.kts # gradle/wrapper/gradle-wrapper.properties
2026-02-07.14-04-35.mp4 |
|
this PR is bundled also with:
|
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a well-structured player mention system with sound notifications. The separation of core logic, configuration, and the Paper-specific implementation is clean, and the inclusion of unit tests for the detection logic is a great practice.
However, there are a few discrepancies between the pull request description and the implemented code that should be addressed:
- The
/chatformatter mentiontogglecommand and the associated per-player settings (mention-settings.yml,enabledByDefaultconfig) are mentioned as part of this PR but have not been implemented. The command handler has been refactored to support subcommands, which is a good step, but only thereloadcommand is present. - The filtering of self-mentions was also mentioned but is missing from the implementation. I've added a specific comment with a suggestion to fix this.
Overall, this is a solid foundation for the mentions feature. Addressing the missing pieces will bring it in line with the described functionality.
chatformatter-core/src/main/java/com/eternalcode/formatter/ChatHandlerImpl.java
Outdated
Show resolved
Hide resolved
chatformatter-core/src/main/java/com/eternalcode/formatter/mention/MentionDetector.java
Outdated
Show resolved
Hide resolved
…tion/MentionDetector.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
633bc02 to
94f4b86
Compare
94f4b86 to
5ac4ff7
Compare
| import java.util.Map; | ||
| import java.util.Optional; | ||
|
|
||
| import static net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We dont use static imports
| List<Player> players = detectMentions(message); | ||
| Sound sound = loadSound(); | ||
|
|
||
| for (Player player : players) { | ||
| player.playSound(player.getLocation(), sound, config.mentions.volume, config.mentions.pitch); | ||
| } | ||
| } | ||
|
|
||
| private List<Player> detectMentions(String message) { | ||
| if (!this.config.mentions.enabled) { | ||
| return List.of(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| List<Player> players = detectMentions(message); | |
| Sound sound = loadSound(); | |
| for (Player player : players) { | |
| player.playSound(player.getLocation(), sound, config.mentions.volume, config.mentions.pitch); | |
| } | |
| } | |
| private List<Player> detectMentions(String message) { | |
| if (!this.config.mentions.enabled) { | |
| return List.of(); | |
| } | |
| if (!this.config.mentions.enabled) { | |
| return List.of(); | |
| } | |
| List<Player> players = detectMentions(message); | |
| Sound sound = loadSound(); | |
| for (Player player : players) { | |
| player.playSound(player.getLocation(), sound, config.mentions.volume, config.mentions.pitch); | |
| } | |
| } | |
| private List<Player> detectMentions(String message) { |
| } | ||
|
|
||
| void mentionPlayers(String message) { | ||
| List<Player> players = detectMentions(message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| List<Player> players = detectMentions(message); | |
| List<Player> mentionedPlayers = detectMentions(message); |
CitralFlo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few suggestions:
- Add support for mentions without
@-> meaning entering a username in chat would ping the user - Make username mention configurable - so users can add hover or change the color of mentions in chat
Possible alternative:
- Use packetEvents to support suggestions when user enters
@in chat - Move matcher logic to process only messages containing the
@xxx- less work for the Service
| @Contextual | ||
| public class MentionConfig implements Serializable { | ||
|
|
||
| @Description({ " ", "# Mention system configuration" }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @Description({ " ", "# Mention system configuration" }) | |
| @Description("# Mention system configuration") |
| @Description("# When a player mentions another player with @playername, the mentioned player will hear a sound") | ||
| public boolean enabled = true; | ||
|
|
||
| @Description({ " ", "# The sound to play when a player is mentioned" }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @Description({ " ", "# The sound to play when a player is mentioned" }) | |
| @Description("# The sound to play when a player is mentioned") |
| @Description("# Available sounds: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Sound.html") | ||
| public String sound = "BLOCK_NOTE_BLOCK_PLING"; | ||
|
|
||
| @Description({ " ", "# The volume of the mention sound (0.0 to 1.0)" }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @Description({ " ", "# The volume of the mention sound (0.0 to 1.0)" }) | |
| @Description("# The volume of the mention sound (0.0 to 1.0)") |
| @Description({ " ", "# The volume of the mention sound (0.0 to 1.0)" }) | ||
| public float volume = 1.0f; | ||
|
|
||
| @Description({ " ", "# The pitch of the mention sound (0.5 to 2.0)" }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @Description({ " ", "# The pitch of the mention sound (0.5 to 2.0)" }) | |
| @Description("# The pitch of the mention sound (0.5 to 2.0)") |
|
|
||
| @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) | ||
| void onMention(AsyncPlayerChatEvent event) { | ||
| mentionService.mentionPlayers(event.getMessage()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| mentionService.mentionPlayers(event.getMessage()); | |
| this.mentionService.mentionPlayers(event.getMessage()); |
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| // Mentions | ||
| this.mentionService = new MentionService(server, pluginConfig); | ||
| server.getPluginManager().registerEvents(new MentionListener(mentionService), plugin); | ||
|
|
||
| // Update checker | ||
| server.getPluginManager().registerEvents(new UpdaterController(updaterService, pluginConfig, audienceProvider, miniMessage), plugin); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments prbly not needed here
Adds player mentions via
@playernamesyntax with configurable sound notifications and per-player toggle controls.Architecture
Core (
chatformatter-core)MentionDetector- Regex-based detection of@[a-zA-Z0-9_]{3,16}patterns, returns online players onlyMentionService- Coordinates detectionMentionConfig- Config schema for sound type, volume, pitch, and default stateChatRenderedMessagerecord withList<Player> mentionedPlayersfieldChatHandlerImpl.process()to detect mentions from raw message textPaper Integration (
chatformatter-paper-plugin)MentionSoundHandler- Plays configured sound to mentioned playersPaperChatEventExecutorto trigger sounds whenmentionedPlayersis non-emptyCommands
ChatFormatterCommandwith switch expression pattern for subcommandsConfiguration
Usage
Testing
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
hub.spigotmc.org/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -XX:MaxMetaspaceSize=384m -XX:+HeapDumpOnOutOfMemoryError -Xms256m -Xmx512m -Dfile.encoding=UTF-8(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.