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
5 changes: 5 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ jobs:
version: ${{ github.event.release.tag_name }}
changelog: ${{ github.event.release.body }}
loaders: paper
dependencies: |-
[{
"project_id": "lKEzGugV",
"dependency_type": "optional"
}]
game-versions: |-
1.20.x
1.21.x
Expand Down
32 changes: 32 additions & 0 deletions .run/Package.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Package" type="MavenRunConfiguration" factoryName="Maven">
<MavenSettings>
<option name="myGeneralSettings" />
<option name="myRunnerSettings" />
<option name="myRunnerParameters">
<MavenRunnerParameters>
<option name="cmdOptions" />
<option name="profiles">
<set />
</option>
<option name="goals">
<list>
<option value="package" />
</list>
</option>
<option name="multimoduleDir" />
<option name="pomFileName" />
<option name="profilesMap">
<map />
</option>
<option name="projectsCmdOptionValues">
<list />
</option>
<option name="resolveToWorkspace" value="false" />
<option name="workingDirPath" value="$PROJECT_DIR$" />
</MavenRunnerParameters>
</option>
</MavenSettings>
<method v="2" />
</configuration>
</component>
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
<repository>
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/releases/</url>
</repository>
</repositories>

<dependencies>
Expand All @@ -81,5 +85,11 @@
<version>1.20.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
51 changes: 51 additions & 0 deletions src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
package pro.cloudnode.smp.cloudnodemsg;

import io.papermc.paper.chat.ChatRenderer;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
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.OfflinePlayer;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.Team;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;
import java.util.Optional;

public final class PluginConfig {
public @NotNull FileConfiguration config;
Expand Down Expand Up @@ -305,6 +318,44 @@ public PluginConfig(final @NotNull FileConfiguration config) {
);
}

/**
* Chat format
*/
public @NotNull Optional<@NotNull ChatRenderer> chatFormat() {
final @Nullable String str = config.getString("chat-format");
if (str == null || str.equals("null") || str.isBlank())
return Optional.empty();
return Optional.of((source, sourceDisplayName, message, viewer) -> MiniMessage.miniMessage().deserialize(
str,
Placeholder.component("message", message),
TagResolver.resolver("papi", (args, ctx) -> {
String placeholder = args.popOr("placeholder expected").value().trim();
if (!placeholder.startsWith("%") && !placeholder.endsWith("%"))
placeholder = "%" + placeholder + "%";
if (!CloudnodeMSG.getInstance().getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
CloudnodeMSG.getInstance().getLogger().severe("Attempted to use PlaceholderAPI placeholder `" + placeholder
+ "` in chat format, but PlaceholderAPI is not present!");
return Tag.inserting(Component.text(PlaceholderAPI.setPlaceholders(source, placeholder)));
}),
TagResolver.resolver("has-team", (args, ctx) -> {
final String text = args.popOr("text expected").value();
final Team team = source.getScoreboard().getPlayerTeam(source);
if (team == null) {
if (args.hasNext())
return Tag.inserting(MiniMessage.miniMessage().deserialize(args.popOr("expected fallback value").value()));
else return Tag.inserting(Component.empty());
}
return Tag.inserting(ctx.deserialize(text,
Placeholder.component("team", team.displayName())
));
}),
TagResolver.resolver("player", (args, ctx) -> Tag.inserting(
Component.text(source.getName())
.clickEvent(ClickEvent.suggestCommand("/tell " + source.getName() + " "))
))
));
}

/**
* No permission
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package pro.cloudnode.smp.cloudnodemsg.listener;

import io.papermc.paper.chat.ChatRenderer;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.entity.Player;
Expand All @@ -23,7 +25,7 @@
import java.util.Set;

public final class AsyncChatListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
@EventHandler(priority = EventPriority.LOWEST)
public void ignore(final @NotNull AsyncChatEvent event) {
final @NotNull Set<@NotNull Audience> audience = event.viewers();
final @NotNull Iterator<@NotNull Audience> iterator = audience.iterator();
Expand All @@ -41,7 +43,7 @@ public void ignore(final @NotNull AsyncChatEvent event) {
}
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGHEST)
public void channels(final @NotNull AsyncChatEvent event) {
final @NotNull Player sender = event.getPlayer();
final @NotNull Optional<@NotNull OfflinePlayer> channelRecipient = Message.getChannel(sender);
Expand All @@ -55,7 +57,7 @@ public void channels(final @NotNull AsyncChatEvent event) {
}
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGHEST)
public void teamChannel(final @NotNull AsyncChatEvent event) {
final @NotNull Player sender = event.getPlayer();
if (!Message.hasTeamChannel(sender)) return;
Expand All @@ -68,4 +70,10 @@ public void teamChannel(final @NotNull AsyncChatEvent event) {
}
TeamMessageCommand.sendTeamMessage(sender, team.get(), event.message());
}

@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void chatFormat(final @NotNull AsyncChatEvent event) {
final @NotNull Optional<@NotNull ChatRenderer> format = CloudnodeMSG.getInstance().config().chatFormat();
format.ifPresent(event::renderer);
}
}
14 changes: 14 additions & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ toggle:
# <player> - the player's username
other: "<green>(!) Re-enabled receiving of private messages for <gray><player></gray>.</green>"

# Set custom global/public chat format. Disabled by default.
#
# Placeholders:
# <has-team:'if yes':'if no'> - show a different message based on whether the player is in a team
# <team> - the player's team display name (only works in <has-team>)
# <player> - the name of the player, when clicked suggests command `/tell` followed by the player's name
# <message> - the message being sent in chat
# <papi:…> - use a PlaceholderAPI placeholder, example `<papi:%player_displayname%>` or `<papi:player_displayname>`.
# Requires PlaceholderAPI to be installed.
#
# Example:
#chat-format: <has-team:'<dark_gray>[<white><team></white>]</dark_gray> '><white><player></white><dark_gray>:</dark_gray> <gray><message></gray>
chat-format: null

# Error messages
errors:
# No permission
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ version: '${project.version}'
main: pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG
api-version: '1.20'
author: Cloudnode
softdepend:
- PlaceholderAPI
commands:
message:
description: Send a private message
Expand Down