Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ public void send(final @NotNull Context context) throws InvalidPlayerError {
setReplyTo(sender, recipient);
if (recipient.getUniqueId().equals(console.getUniqueId()) || (recipientPlayer.isPresent() && !Message.hasChannel(recipientPlayer.get(), sender)))
setReplyTo(recipient, sender);

senderPlayer.ifPresent(player -> CloudnodeMSG.getInstance()
.config()
.sound(PluginConfig.SoundEvent.PERSONAL_OUTGOING)
.ifPresent(sound -> sound.play(player))
);
recipientPlayer.ifPresent(player -> CloudnodeMSG.getInstance()
.config()
.sound(PluginConfig.SoundEvent.PERSONAL_INCOMING)
.ifPresent(sound -> sound.play(player))
);
}

public final static @NotNull OfflinePlayer console = CloudnodeMSG.getInstance().getServer()
Expand Down Expand Up @@ -315,7 +326,7 @@ public static boolean hasTeamChannel(final @NotNull Player player) {
/**
* The context in which this message is sent
*/
public static enum Context {
public enum Context {
/**
* Message sent via command (i.e. no special context)
*/
Expand Down
51 changes: 50 additions & 1 deletion src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.Registry;
import org.bukkit.Sound;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.Team;
Expand Down Expand Up @@ -356,6 +359,34 @@ public PluginConfig(final @NotNull FileConfiguration config) {
));
}

public @NotNull Optional<@NotNull ConfiguredSound> sound(final @NotNull SoundEvent event) {
final @Nullable String name = config.getString(String.format("sound.%s.sound", event.key));
if (name == null || name.isBlank() || name.equalsIgnoreCase("null") || name.equalsIgnoreCase("none")) {
return Optional.empty();
}

final @Nullable NamespacedKey key = name.indexOf(':') > -1
? NamespacedKey.fromString(name)
: NamespacedKey.minecraft(name);

if (key == null) {
CloudnodeMSG.getInstance().getLogger().warning(String.format("Invalid sound identifier ‘%s’ for sound event ‘%s’", name, event.key));
return Optional.empty();
}

final @Nullable Sound sound = Registry.SOUNDS.get(key);

if (sound == null) {
CloudnodeMSG.getInstance().getLogger().warning(String.format("Unknown sound ‘%s’ for sound event ‘%s’", name, event.key));
return Optional.empty();
}

final float volume = (float) config.getDouble(String.format("sound.%s.volume", event.key), 1.0);
final float pitch = (float) config.getDouble(String.format("sound.%s.pitch", event.key), 1.0);

return Optional.of(new ConfiguredSound(sound, volume, pitch));
}

/**
* No permission
*/
Expand Down Expand Up @@ -476,5 +507,23 @@ public PluginConfig(final @NotNull FileConfiguration config) {
public @NotNull Component notInTeam() {
return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.not-in-team")));
}
}

public enum SoundEvent {
PERSONAL_INCOMING("personal.incoming"),
PERSONAL_OUTGOING("personal.outgoing"),
TEAM_INCOMING("team.incoming"),
TEAM_OUTGOING("team.outgoing");

public final @NotNull String key;

SoundEvent(final @NotNull String key) {
this.key = key;
}
}

public record ConfiguredSound(@NotNull Sound sound, float volume, float pitch) {
public void play(final @NotNull Player player) {
player.playSound(player, sound, volume, pitch);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG;
import pro.cloudnode.smp.cloudnodemsg.Message;
import pro.cloudnode.smp.cloudnodemsg.Permissions;
import pro.cloudnode.smp.cloudnodemsg.PluginConfig;
import pro.cloudnode.smp.cloudnodemsg.error.NoPermissionError;
import pro.cloudnode.smp.cloudnodemsg.error.NotInTeamError;
import pro.cloudnode.smp.cloudnodemsg.error.NotPlayerError;
Expand Down Expand Up @@ -48,7 +49,19 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la
* Send message to online team members
*/
public static boolean sendTeamMessage(final @NotNull Player sender, final @NotNull Team team, final @NotNull Component message) {
CloudnodeMSG.getInstance()
.config()
.sound(PluginConfig.SoundEvent.TEAM_OUTGOING)
.ifPresent(sound -> sound.play(sender));

for (final @NotNull Player player : sender.getServer().getOnlinePlayers()) {
if (!sender.getUniqueId().equals(player.getUniqueId())) {
CloudnodeMSG.getInstance()
.config()
.sound(PluginConfig.SoundEvent.TEAM_INCOMING)
.ifPresent(sound -> sound.play(player));
}

if (Message.isIgnored(player, sender)) continue;
if (Optional.ofNullable(player.getScoreboard().getPlayerTeam(player)).map(t -> t.equals(team))
.orElse(false))
Expand Down
86 changes: 59 additions & 27 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,36 @@
# <sender> - the username of the message sender
# <recipient> - the username of the message recipient
# <message> - the message text
incoming: '<click:suggest_command:/msg <sender> ><dark_gray>[<#60a5fa><sender></#60a5fa> <white>-></white> <#bfdbfe>me</#bfdbfe>]</dark_gray></click> <reset><#dbeafe><message></#dbeafe>'
incoming: <click:suggest_command:/msg <sender> ><dark_gray>[<#60a5fa><sender></#60a5fa> <white>-></white> <#bfdbfe>me</#bfdbfe>]</dark_gray></click> <reset><#dbeafe><message></#dbeafe>

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

# Team message
# Uses the vanilla teams from `/team`
# Placeholders:
# <sender> - the username of the message sender
# <team> - team display name
# <message> - the message text
team: '<click:suggest_command:/tm ><dark_gray>[<white><team></white>] <gray><sender></gray>:</dark_gray> <white><message></white></click>'
team: <click:suggest_command:/tm ><dark_gray>[<white><team></white>] <gray><sender></gray>:</dark_gray> <white><message></white></click>

# Private message format as seen by people with the spy permission and console
# Same placeholders as incoming
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>'
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>

# Team message format as seen by people with the spy permission and console
# Same placeholders as team
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>'
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>

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

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

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

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

# Command usage format
# Placeholders:
# <command> - the command name
# <usage> - the command usage parameters
usage: "<yellow>(!) Usage:</yellow> <white>/<command> <usage></white>"
usage: <yellow>(!) Usage:</yellow> <white>/<command> <usage></white>

# Plugin reloaded
reloaded: "<green>(!) Plugin successfully reloaded.</green>"
reloaded: <green>(!) Plugin successfully reloaded.</green>

toggle:
disable:
# Disable private messages
message: "<yellow>(!) Receiving private messages is now disabled. Run again to re-enable.</yellow>"
message: <yellow>(!) Receiving private messages is now disabled. Run again to re-enable.</yellow>
# Placeholders:
# <player> - the player's username
other: "<green>(!) Receiving private messages now disabled for <gray><player></gray>.</green>"
other: <green>(!) Receiving private messages now disabled for <gray><player></gray>.</green>
enable:
# Enable private messages
message: "<green>(!) You can now receive private messages again.</green>"
message: <green>(!) You can now receive private messages again.</green>
# Placeholders:
# <player> - the player's username
other: "<green>(!) Re-enabled receiving of private messages for <gray><player></gray>.</green>"
other: <green>(!) Re-enabled receiving of private messages for <gray><player></gray>.</green>

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

# Play a sound…
sound:
personal:
# …when receiving a private message
incoming:
# The ID of the sound.
# Set to null, none, or "" to disable.
sound: entity.chicken.egg

# Volume of the sound from 0.0 to 1.0. Decrease to be quieter.
volume: 1.0

# Pitch of the sound from 0.5 to 2.0.
# Optional: defaults to 1.0.
# Values below 1.0 lower the pitch and increase the duration;
# values above 1.0 raise the pitch and reduce the duration.
pitch: 0.82

# …when sending a private message
outgoing:
sound: null

team:
# …when receiving a team message
incoming:
sound: ui.hud.bubble_pop
pitch: .7

# …when sending a team message
outgoing:
sound: null

# Error messages
errors:
# No permission
no-permission: "<red>(!) You don't have permission to use this command.</red>"
no-permission: <red>(!) You don't have permission to use this command.</red>

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

# Player not found
# Placeholders:
# <player> - the player's username
player-not-found: "<red>(!) Player <gray><player></gray> not found.</red>"
player-not-found: <red>(!) Player <gray><player></gray> not found.</red>

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

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

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

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

# That player is not ignored
# Placeholders:
# <player> - the player's username
not-ignored: "<red>(!) You are not ignoring that player.</red>"
not-ignored: <red>(!) You are not ignoring that player.</red>

# Player cannot be ignored
# Placeholders:
# <player> - the player's username
cannot-ignore: "<red>(!) You cannot ignore <gray><player></gray>.</red>"
cannot-ignore: <red>(!) You cannot ignore <gray><player></gray>.</red>

# You are trying to ignore yourself
ignore-yourself: "<red>(!) You cannot ignore yourself.</red>"
ignore-yourself: <red>(!) You cannot ignore yourself.</red>

# Target player has never joined the server
# Placeholders:
# <player> - the player's username
never-joined: "<red>(!) <gray><player></gray> has never joined this server.</red>"
never-joined: <red>(!) <gray><player></gray> has never joined this server.</red>

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

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