Skip to content

Commit 9c455fd

Browse files
authored
Added configurable message sounds (#79)
2 parents 4628f8f + 25b12ea commit 9c455fd

6 files changed

Lines changed: 135 additions & 30 deletions

File tree

.idea/codeStyles/Project.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/codeStyles/codeStyleConfig.xml

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ public void send(final @NotNull Context context) throws InvalidPlayerError {
8989
setReplyTo(sender, recipient);
9090
if (recipient.getUniqueId().equals(console.getUniqueId()) || (recipientPlayer.isPresent() && !Message.hasChannel(recipientPlayer.get(), sender)))
9191
setReplyTo(recipient, sender);
92+
93+
senderPlayer.ifPresent(player -> CloudnodeMSG.getInstance()
94+
.config()
95+
.sound(PluginConfig.SoundEvent.PERSONAL_OUTGOING)
96+
.ifPresent(sound -> sound.play(player))
97+
);
98+
recipientPlayer.ifPresent(player -> CloudnodeMSG.getInstance()
99+
.config()
100+
.sound(PluginConfig.SoundEvent.PERSONAL_INCOMING)
101+
.ifPresent(sound -> sound.play(player))
102+
);
92103
}
93104

94105
public final static @NotNull OfflinePlayer console = CloudnodeMSG.getInstance().getServer()
@@ -315,7 +326,7 @@ public static boolean hasTeamChannel(final @NotNull Player player) {
315326
/**
316327
* The context in which this message is sent
317328
*/
318-
public static enum Context {
329+
public enum Context {
319330
/**
320331
* Message sent via command (i.e. no special context)
321332
*/

src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
import net.kyori.adventure.text.minimessage.tag.Tag;
1313
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
1414
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
15+
import org.bukkit.NamespacedKey;
1516
import org.bukkit.OfflinePlayer;
17+
import org.bukkit.Registry;
18+
import org.bukkit.Sound;
1619
import org.bukkit.configuration.file.FileConfiguration;
1720
import org.bukkit.entity.Player;
1821
import org.bukkit.scoreboard.Team;
@@ -356,6 +359,34 @@ public PluginConfig(final @NotNull FileConfiguration config) {
356359
));
357360
}
358361

362+
public @NotNull Optional<@NotNull ConfiguredSound> sound(final @NotNull SoundEvent event) {
363+
final @Nullable String name = config.getString(String.format("sound.%s.sound", event.key));
364+
if (name == null || name.isBlank() || name.equalsIgnoreCase("null") || name.equalsIgnoreCase("none")) {
365+
return Optional.empty();
366+
}
367+
368+
final @Nullable NamespacedKey key = name.indexOf(':') > -1
369+
? NamespacedKey.fromString(name)
370+
: NamespacedKey.minecraft(name);
371+
372+
if (key == null) {
373+
CloudnodeMSG.getInstance().getLogger().warning(String.format("Invalid sound identifier ‘%s’ for sound event ‘%s’", name, event.key));
374+
return Optional.empty();
375+
}
376+
377+
final @Nullable Sound sound = Registry.SOUNDS.get(key);
378+
379+
if (sound == null) {
380+
CloudnodeMSG.getInstance().getLogger().warning(String.format("Unknown sound ‘%s’ for sound event ‘%s’", name, event.key));
381+
return Optional.empty();
382+
}
383+
384+
final float volume = (float) config.getDouble(String.format("sound.%s.volume", event.key), 1.0);
385+
final float pitch = (float) config.getDouble(String.format("sound.%s.pitch", event.key), 1.0);
386+
387+
return Optional.of(new ConfiguredSound(sound, volume, pitch));
388+
}
389+
359390
/**
360391
* No permission
361392
*/
@@ -476,5 +507,23 @@ public PluginConfig(final @NotNull FileConfiguration config) {
476507
public @NotNull Component notInTeam() {
477508
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.not-in-team")));
478509
}
479-
}
480510

511+
public enum SoundEvent {
512+
PERSONAL_INCOMING("personal.incoming"),
513+
PERSONAL_OUTGOING("personal.outgoing"),
514+
TEAM_INCOMING("team.incoming"),
515+
TEAM_OUTGOING("team.outgoing");
516+
517+
public final @NotNull String key;
518+
519+
SoundEvent(final @NotNull String key) {
520+
this.key = key;
521+
}
522+
}
523+
524+
public record ConfiguredSound(@NotNull Sound sound, float volume, float pitch) {
525+
public void play(final @NotNull Player player) {
526+
player.playSound(player, sound, volume, pitch);
527+
}
528+
}
529+
}

src/main/java/pro/cloudnode/smp/cloudnodemsg/command/TeamMessageCommand.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
1010
import pro.cloudnode.smp.cloudnodemsg.Message;
1111
import pro.cloudnode.smp.cloudnodemsg.Permissions;
12+
import pro.cloudnode.smp.cloudnodemsg.PluginConfig;
1213
import pro.cloudnode.smp.cloudnodemsg.error.NoPermissionError;
1314
import pro.cloudnode.smp.cloudnodemsg.error.NotInTeamError;
1415
import pro.cloudnode.smp.cloudnodemsg.error.NotPlayerError;
@@ -48,7 +49,19 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la
4849
* Send message to online team members
4950
*/
5051
public static boolean sendTeamMessage(final @NotNull Player sender, final @NotNull Team team, final @NotNull Component message) {
52+
CloudnodeMSG.getInstance()
53+
.config()
54+
.sound(PluginConfig.SoundEvent.TEAM_OUTGOING)
55+
.ifPresent(sound -> sound.play(sender));
56+
5157
for (final @NotNull Player player : sender.getServer().getOnlinePlayers()) {
58+
if (!sender.getUniqueId().equals(player.getUniqueId())) {
59+
CloudnodeMSG.getInstance()
60+
.config()
61+
.sound(PluginConfig.SoundEvent.TEAM_INCOMING)
62+
.ifPresent(sound -> sound.play(player));
63+
}
64+
5265
if (Message.isIgnored(player, sender)) continue;
5366
if (Optional.ofNullable(player.getScoreboard().getPlayerTeam(player)).map(t -> t.equals(team))
5467
.orElse(false))

src/main/resources/config.yml

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,36 @@
33
# <sender> - the username of the message sender
44
# <recipient> - the username of the message recipient
55
# <message> - the message text
6-
incoming: '<click:suggest_command:/msg <sender> ><dark_gray>[<#60a5fa><sender></#60a5fa> <white>-></white> <#bfdbfe>me</#bfdbfe>]</dark_gray></click> <reset><#dbeafe><message></#dbeafe>'
6+
incoming: <click:suggest_command:/msg <sender> ><dark_gray>[<#60a5fa><sender></#60a5fa> <white>-></white> <#bfdbfe>me</#bfdbfe>]</dark_gray></click> <reset><#dbeafe><message></#dbeafe>
77

88
# Outgoing message format (sender's point of view)
99
# Same placeholders as incoming
10-
outgoing: '<click:suggest_command:/msg <recipient> ><dark_gray>[<#93c5fd>me</#93c5fd> <white>-></white> <#60a5fa><recipient></#60a5fa>]</dark_gray></click> <reset><#dbeafe><message></#dbeafe>'
10+
outgoing: <click:suggest_command:/msg <recipient> ><dark_gray>[<#93c5fd>me</#93c5fd> <white>-></white> <#60a5fa><recipient></#60a5fa>]</dark_gray></click> <reset><#dbeafe><message></#dbeafe>
1111

1212
# Team message
1313
# Uses the vanilla teams from `/team`
1414
# Placeholders:
1515
# <sender> - the username of the message sender
1616
# <team> - team display name
1717
# <message> - the message text
18-
team: '<click:suggest_command:/tm ><dark_gray>[<white><team></white>] <gray><sender></gray>:</dark_gray> <white><message></white></click>'
18+
team: <click:suggest_command:/tm ><dark_gray>[<white><team></white>] <gray><sender></gray>:</dark_gray> <white><message></white></click>
1919

2020
# Private message format as seen by people with the spy permission and console
2121
# Same placeholders as incoming
22-
spy: '<dark_gray>[SPY] [<click:suggest_command:/msg <sender> ><gray><sender></gray></click> -> <click:suggest_command:/msg <recipient> ><gray><recipient></gray></click>] <gray><message></gray></dark_gray>'
22+
spy: <dark_gray>[SPY] [<click:suggest_command:/msg <sender> ><gray><sender></gray></click> -> <click:suggest_command:/msg <recipient> ><gray><recipient></gray></click>] <gray><message></gray></dark_gray>
2323

2424
# Team message format as seen by people with the spy permission and console
2525
# Same placeholders as team
26-
team-spy: '<dark_gray>[SPY]</dark_gray> <dark_gray>[<white><team></white>] <gray><click:suggest_command:/msg <sender> ><sender></click></gray>:</dark_gray> <gray><message></gray>'
26+
team-spy: <dark_gray>[SPY]</dark_gray> <dark_gray>[<white><team></white>] <gray><click:suggest_command:/msg <sender> ><sender></click></gray>:</dark_gray> <gray><message></gray>
2727

2828
# Player has successfully been ignored
2929
# Placeholders:
3030
# <player> - the player's username
31-
ignored: "<green>(!) You will no longer see messages from <gray><player></gray>.</green>"
31+
ignored: <green>(!) You will no longer see messages from <gray><player></gray>.</green>
3232

3333
# Player has successfully been unignored
3434
# Same placeholders as ignored
35-
unignored: "<yellow>(!) You are no longer ignoring <gray><player></gray>.</yellow>"
35+
unignored: <yellow>(!) You are no longer ignoring <gray><player></gray>.</yellow>
3636

3737
channel:
3838
# Message channel created
@@ -63,30 +63,30 @@ channel:
6363
team-closed: <yellow>(!) Your chat messages will now be <gray>public</gray>.</yellow>
6464

6565
# Name for console/server that should appear as <sender> or <recipient> in messages
66-
console-name: "Server"
66+
console-name: Server
6767

6868
# Command usage format
6969
# Placeholders:
7070
# <command> - the command name
7171
# <usage> - the command usage parameters
72-
usage: "<yellow>(!) Usage:</yellow> <white>/<command> <usage></white>"
72+
usage: <yellow>(!) Usage:</yellow> <white>/<command> <usage></white>
7373

7474
# Plugin reloaded
75-
reloaded: "<green>(!) Plugin successfully reloaded.</green>"
75+
reloaded: <green>(!) Plugin successfully reloaded.</green>
7676

7777
toggle:
7878
disable:
7979
# Disable private messages
80-
message: "<yellow>(!) Receiving private messages is now disabled. Run again to re-enable.</yellow>"
80+
message: <yellow>(!) Receiving private messages is now disabled. Run again to re-enable.</yellow>
8181
# Placeholders:
8282
# <player> - the player's username
83-
other: "<green>(!) Receiving private messages now disabled for <gray><player></gray>.</green>"
83+
other: <green>(!) Receiving private messages now disabled for <gray><player></gray>.</green>
8484
enable:
8585
# Enable private messages
86-
message: "<green>(!) You can now receive private messages again.</green>"
86+
message: <green>(!) You can now receive private messages again.</green>
8787
# Placeholders:
8888
# <player> - the player's username
89-
other: "<green>(!) Re-enabled receiving of private messages for <gray><player></gray>.</green>"
89+
other: <green>(!) Re-enabled receiving of private messages for <gray><player></gray>.</green>
9090

9191
# Set custom global/public chat format. Disabled by default.
9292
#
@@ -102,53 +102,85 @@ toggle:
102102
#chat-format: <has-team:'<dark_gray>[<white><team></white>]</dark_gray> '><white><player></white><dark_gray>:</dark_gray> <gray><message></gray>
103103
chat-format: null
104104

105+
# Play a sound…
106+
sound:
107+
personal:
108+
# …when receiving a private message
109+
incoming:
110+
# The ID of the sound.
111+
# Set to null, none, or "" to disable.
112+
sound: entity.chicken.egg
113+
114+
# Volume of the sound from 0.0 to 1.0. Decrease to be quieter.
115+
volume: 1.0
116+
117+
# Pitch of the sound from 0.5 to 2.0.
118+
# Optional: defaults to 1.0.
119+
# Values below 1.0 lower the pitch and increase the duration;
120+
# values above 1.0 raise the pitch and reduce the duration.
121+
pitch: 0.82
122+
123+
# …when sending a private message
124+
outgoing:
125+
sound: null
126+
127+
team:
128+
# …when receiving a team message
129+
incoming:
130+
sound: ui.hud.bubble_pop
131+
pitch: .7
132+
133+
# …when sending a team message
134+
outgoing:
135+
sound: null
136+
105137
# Error messages
106138
errors:
107139
# No permission
108-
no-permission: "<red>(!) You don't have permission to use this command.</red>"
140+
no-permission: <red>(!) You don't have permission to use this command.</red>
109141

110142
# Player has no username (somehow)
111-
invalid-player: "<red>(!) Invalid player.</red>"
143+
invalid-player: <red>(!) Invalid player.</red>
112144

113145
# Player not found
114146
# Placeholders:
115147
# <player> - the player's username
116-
player-not-found: "<red>(!) Player <gray><player></gray> not found.</red>"
148+
player-not-found: <red>(!) Player <gray><player></gray> not found.</red>
117149

118-
message-yourself: "<red>(!) You can't send a message to yourself.</red>"
150+
message-yourself: <red>(!) You can't send a message to yourself.</red>
119151

120-
nobody-reply: "<red>(!) You have no one to reply to.</red>"
152+
nobody-reply: <red>(!) You have no one to reply to.</red>
121153

122154
# The player that messaged you is no longer online
123155
# Placeholders:
124156
# <player> - the player's username
125-
reply-offline: "<red>(!) Player <gray><player></gray> is no longer online.</red>"
157+
reply-offline: <red>(!) Player <gray><player></gray> is no longer online.</red>
126158

127159
# Only players can use this command
128-
not-player: "<red>(!) You must be a player to use this command.</red>"
160+
not-player: <red>(!) You must be a player to use this command.</red>
129161

130162
# That player is not ignored
131163
# Placeholders:
132164
# <player> - the player's username
133-
not-ignored: "<red>(!) You are not ignoring that player.</red>"
165+
not-ignored: <red>(!) You are not ignoring that player.</red>
134166

135167
# Player cannot be ignored
136168
# Placeholders:
137169
# <player> - the player's username
138-
cannot-ignore: "<red>(!) You cannot ignore <gray><player></gray>.</red>"
170+
cannot-ignore: <red>(!) You cannot ignore <gray><player></gray>.</red>
139171

140172
# You are trying to ignore yourself
141-
ignore-yourself: "<red>(!) You cannot ignore yourself.</red>"
173+
ignore-yourself: <red>(!) You cannot ignore yourself.</red>
142174

143175
# Target player has never joined the server
144176
# Placeholders:
145177
# <player> - the player's username
146-
never-joined: "<red>(!) <gray><player></gray> has never joined this server.</red>"
178+
never-joined: <red>(!) <gray><player></gray> has never joined this server.</red>
147179

148180
# Target player have disabled their incoming private messages.
149181
# Placeholders:
150182
# <player> - the player's username
151-
incoming-disabled: "<red>(!) You cannot message <gray><player></gray> because they have disabled private messages.</red>"
183+
incoming-disabled: <red>(!) You cannot message <gray><player></gray> because they have disabled private messages.</red>
152184

153185
# Trying to message a team, but not in one
154-
not-in-team: "<red>(!) You are not in a team.</red>"
186+
not-in-team: <red>(!) You are not in a team.</red>

0 commit comments

Comments
 (0)