From 2af29fe6bf27404927c110311ef7d32b7deee5d7 Mon Sep 17 00:00:00 2001 From: kento2 Date: Wed, 8 Jul 2026 15:15:58 +0200 Subject: [PATCH] prefixes --- README.md | 2 +- .../java/de/kentoj/scrow/bukkit/ScrowAPI.java | 9 +++ core-bukkit-impl/build.gradle.kts | 1 + .../kentoj/scrow/bukkit/CoreImplPlugin.java | 30 +++++---- .../kentoj/scrow/bukkit/ScrowAPISurface.java | 7 +- .../bukkit/chatstyle/ChatStyleListener.java | 32 --------- .../chatstyle/LuckPermsPrefixCache.java | 36 ---------- .../bukkit/chatstyle/NoPrefixPrefixCache.java | 13 ---- .../scrow/bukkit/chatstyle/PrefixCache.java | 11 ---- .../NetworkPlayerWatchdog.java | 2 +- .../player/prefix/CachedPrefixProvider.java | 37 +++++++++++ .../player/prefix/LuckPermsPrefixSetter.java | 65 +++++++++++++++++++ .../scrow/bukkit/style/ChatStyleListener.java | 23 +++++++ .../scrow/bukkit/style/StyleHelper.java | 26 ++++++++ .../scrow/bukkit/style/TabStyleListener.java | 37 +++++++++++ .../scrowlib/player/PlayerPrefixProvider.java | 18 +++++ 16 files changed, 241 insertions(+), 108 deletions(-) delete mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/ChatStyleListener.java delete mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/LuckPermsPrefixCache.java delete mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/NoPrefixPrefixCache.java delete mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/PrefixCache.java rename core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/{network => player}/NetworkPlayerWatchdog.java (97%) create mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/prefix/CachedPrefixProvider.java create mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/prefix/LuckPermsPrefixSetter.java create mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/ChatStyleListener.java create mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/StyleHelper.java create mode 100644 core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/TabStyleListener.java create mode 100644 core-lib/src/main/java/de/kentoj/scrowlib/player/PlayerPrefixProvider.java diff --git a/README.md b/README.md index 53ec4a9..a25537a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ TODO +- chat prefix cache - make core-lib-impl: a library -> avoid shading massive core-lib -- logging in general, log some exceptions to game chat - notification: Friend is now offline/online - /ignore command diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java index c391e43..ebba10c 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java @@ -9,11 +9,13 @@ import de.kentoj.scrowlib.player.NetworkPlayerFactory; import de.kentoj.scrow.bukkit.region.RegionManager; import de.kentoj.scrowlib.instancemanager.InstanceManager; import de.kentoj.scrowlib.messaging.MessageBroker; +import de.kentoj.scrowlib.player.PlayerPrefixProvider; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import org.bukkit.OfflinePlayer; import org.bukkit.plugin.Plugin; +import org.checkerframework.checker.signature.qual.InternalForm; import org.jdbi.v3.core.Jdbi; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -44,6 +46,8 @@ public class ScrowAPI { private static RegionManager regionManager; @Getter private static CommandAPI commandApi; + @Getter + private static PlayerPrefixProvider playerPrefixProvider; private static NetworkPlayerFactory playerFactory; public static NetworkPlayer getPlayer(OfflinePlayer player) { @@ -103,5 +107,10 @@ public class ScrowAPI { public static void setPlayerFactory(NetworkPlayerFactory playerFactory) { ScrowAPI.playerFactory = playerFactory; } + + @ApiStatus.Internal + public static void setPlayerPrefixProvider(PlayerPrefixProvider playerPrefixProvider) { + ScrowAPI.playerPrefixProvider = playerPrefixProvider; + } } diff --git a/core-bukkit-impl/build.gradle.kts b/core-bukkit-impl/build.gradle.kts index c033fb6..51e135e 100644 --- a/core-bukkit-impl/build.gradle.kts +++ b/core-bukkit-impl/build.gradle.kts @@ -28,6 +28,7 @@ tasks { downloadPlugins { url("https://hangarcdn.papermc.io/plugins/ViaVersion/ViaVersion/versions/5.7.1/PAPER/ViaVersion-5.7.1.jar") url("https://hangarcdn.papermc.io/plugins/ViaVersion/ViaBackwards/versions/5.7.1/PAPER/ViaBackwards-5.7.1.jar") + url("https://download.luckperms.net/1647/bukkit/loader/LuckPerms-Bukkit-5.5.59.jar") } } } diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/CoreImplPlugin.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/CoreImplPlugin.java index 5c9f156..f5a0226 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/CoreImplPlugin.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/CoreImplPlugin.java @@ -1,13 +1,16 @@ package de.kentoj.scrow.bukkit; -import de.kentoj.scrow.bukkit.chatstyle.ChatStyleListener; -import de.kentoj.scrow.bukkit.chatstyle.NoPrefixPrefixCache; +import de.kentoj.scrow.bukkit.style.ChatStyleListener; import de.kentoj.scrow.bukkit.command.economy.CoinsCommand; import de.kentoj.scrow.bukkit.command.friends.FriendCommand; import de.kentoj.scrow.bukkit.command.instance.InstanceCache; import de.kentoj.scrow.bukkit.command.instance.InstanceCommand; import de.kentoj.scrow.bukkit.command.instance.LobbyCommand; import de.kentoj.scrow.bukkit.command.instance.PlayCommand; +import de.kentoj.scrow.bukkit.internal.player.prefix.CachedPrefixProvider; +import de.kentoj.scrow.bukkit.internal.player.prefix.LuckPermsPrefixSetter; +import de.kentoj.scrow.bukkit.style.TabStyleListener; +import net.luckperms.api.LuckPermsProvider; import org.bukkit.plugin.java.JavaPlugin; import java.io.IOException; @@ -20,17 +23,20 @@ public final class CoreImplPlugin extends JavaPlugin { @Override public void onEnable() { - ScrowAPISurface.initScrowAPI(this); - { - ScrowAPI.getCommandApi().register(new CoinsCommand().getRootLiteral()); - ScrowAPI.getCommandApi().register(FriendCommand.create()); - var instanceCache = new InstanceCache(); - ScrowAPI.getCommandApi().register(InstanceCommand.create(instanceCache)); - ScrowAPI.getCommandApi().register(new PlayCommand().getRootLiteral()); - ScrowAPI.getCommandApi().register(new LobbyCommand().getRootLiteral()); - } + var cachedPrefixProvider = new CachedPrefixProvider(); + ScrowAPISurface.initScrowAPI(this, cachedPrefixProvider); - getServer().getPluginManager().registerEvents(new ChatStyleListener(new NoPrefixPrefixCache()), this); + ScrowAPI.getCommandApi().register(new CoinsCommand().getRootLiteral()); + ScrowAPI.getCommandApi().register(FriendCommand.create()); + var instanceCache = new InstanceCache(); + ScrowAPI.getCommandApi().register(InstanceCommand.create(instanceCache)); + ScrowAPI.getCommandApi().register(new PlayCommand().getRootLiteral()); + ScrowAPI.getCommandApi().register(new LobbyCommand().getRootLiteral()); + + var luckperms = LuckPermsProvider.get(); + new LuckPermsPrefixSetter(luckperms, cachedPrefixProvider).init(this); + getServer().getPluginManager().registerEvents(new ChatStyleListener(cachedPrefixProvider), this); + getServer().getPluginManager().registerEvents(new TabStyleListener(cachedPrefixProvider), this); // TODO/FIXME //registerServer(); diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/ScrowAPISurface.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/ScrowAPISurface.java index 71c2a68..24199ba 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/ScrowAPISurface.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/ScrowAPISurface.java @@ -1,7 +1,8 @@ package de.kentoj.scrow.bukkit; import de.kentoj.kencommandapi.CommandAPI; -import de.kentoj.scrow.bukkit.internal.network.NetworkPlayerWatchdog; +import de.kentoj.scrow.bukkit.internal.player.NetworkPlayerWatchdog; +import de.kentoj.scrow.bukkit.internal.player.prefix.CachedPrefixProvider; import de.kentoj.scrow.bukkit.internal.region.RegionManagerImpl; import de.kentoj.scrow.bukkit.internal.region.RegionPlayerTracker; import de.kentoj.scrow.bukkit.internal.region.RegionTask; @@ -15,6 +16,7 @@ import de.kentoj.scrowlib.instancemanager.InstanceManagerImpl; import de.kentoj.scrowlib.messaging.InMemoyMessageBroker; import de.kentoj.scrowlib.messaging.NatsMessageBroker; import de.kentoj.scrowlib.player.NetworkPlayerImpl; +import de.kentoj.scrowlib.player.PlayerPrefixProvider; import io.nats.client.Nats; import io.nats.client.Options; import lombok.AccessLevel; @@ -30,7 +32,7 @@ import java.util.Properties; @NoArgsConstructor(access = AccessLevel.NONE) public class ScrowAPISurface { - public static void initScrowAPI(Plugin plugin) { + public static void initScrowAPI(Plugin plugin, PlayerPrefixProvider prefixProvider) { ScrowAPI.setCorePlugin(plugin); var natsHost = System.getenv("HOST_NATS"); @@ -73,6 +75,7 @@ public class ScrowAPISurface { new PostgresFriendRequestService(ScrowAPI.getJdbi()) : new InMemoryFriendRequestService()); ScrowAPI.setFriendshipService(ScrowAPI.getJdbi() != null ? new PostgresFriendshipService(ScrowAPI.getJdbi()) : new InMemoryFriendshipService()); + ScrowAPI.setPlayerPrefixProvider(prefixProvider); new RegionTask(new RegionPlayerTracker()).runTaskTimer(plugin, 10, 10); new NetworkPlayerWatchdog().listen(); diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/ChatStyleListener.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/ChatStyleListener.java deleted file mode 100644 index 3e58b30..0000000 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/ChatStyleListener.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.kentoj.scrow.bukkit.chatstyle; - -import de.kentoj.scrowlib.utils.ComponentUtils; -import io.papermc.paper.event.player.AsyncChatEvent; -import lombok.RequiredArgsConstructor; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -@RequiredArgsConstructor -public class ChatStyleListener implements Listener { - - private final PrefixCache prefixCache; - - @EventHandler - public void onChat(AsyncChatEvent ev) { - Component formattedMessage = formatMessage(ev.getPlayer(), ev.message()); - - ev.renderer((source, sourceDisplayName, message, viewer) -> formattedMessage); - } - - private Component formatMessage(Player player, Component message) { - var prefix = prefixCache.getPrefix(player.getUniqueId()); - Component msg = prefix != null - ? prefix.append(Component.text("│").color(NamedTextColor.DARK_GRAY)) - : Component.empty(); - return msg.append(Component.text(player.getName() + ": ").color(NamedTextColor.GRAY)) - .append(ComponentUtils.resolveURLS(message).colorIfAbsent(NamedTextColor.GRAY)); - } -} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/LuckPermsPrefixCache.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/LuckPermsPrefixCache.java deleted file mode 100644 index 80953f5..0000000 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/LuckPermsPrefixCache.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.kentoj.scrow.bukkit.chatstyle; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -import net.luckperms.api.LuckPerms; -import net.luckperms.api.event.user.UserDataRecalculateEvent; -import org.bukkit.Bukkit; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class LuckPermsPrefixCache implements PrefixCache { - private final Map cache = new HashMap<>(); - - // TODO load on join, unload on quit - public LuckPermsPrefixCache(LuckPerms luckPerms) { - //noinspection resource - luckPerms.getEventBus().subscribe(UserDataRecalculateEvent.class, this::onDataChange); - } - - private void onDataChange(UserDataRecalculateEvent ev) { - var playerId = ev.getUser().getUniqueId(); - if (Bukkit.getPlayer(playerId) == null) return; - - var prefix = ev.getUser().getCachedData().getMetaData().getPrefix(); - var prefixComponent = PlainTextComponentSerializer.plainText().deserialize(prefix); - cache.put(playerId, prefixComponent); - } - - @Override - public @Nullable Component getPrefix(UUID playerId) { - return cache.get(playerId); - } -} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/NoPrefixPrefixCache.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/NoPrefixPrefixCache.java deleted file mode 100644 index cf6a460..0000000 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/NoPrefixPrefixCache.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.kentoj.scrow.bukkit.chatstyle; - -import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.Nullable; - -import java.util.UUID; - -public class NoPrefixPrefixCache implements PrefixCache { - @Override - public @Nullable Component getPrefix(UUID playerId) { - return null; - } -} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/PrefixCache.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/PrefixCache.java deleted file mode 100644 index 48575bf..0000000 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/chatstyle/PrefixCache.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.kentoj.scrow.bukkit.chatstyle; - -import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.Nullable; - -import java.util.UUID; - -public interface PrefixCache { - - @Nullable Component getPrefix(UUID playerId); -} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/network/NetworkPlayerWatchdog.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/NetworkPlayerWatchdog.java similarity index 97% rename from core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/network/NetworkPlayerWatchdog.java rename to core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/NetworkPlayerWatchdog.java index cf70f78..d17dd03 100644 --- a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/network/NetworkPlayerWatchdog.java +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/NetworkPlayerWatchdog.java @@ -1,4 +1,4 @@ -package de.kentoj.scrow.bukkit.internal.network; +package de.kentoj.scrow.bukkit.internal.player; import de.kentoj.scrow.bukkit.ScrowAPI; import lombok.RequiredArgsConstructor; diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/prefix/CachedPrefixProvider.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/prefix/CachedPrefixProvider.java new file mode 100644 index 0000000..20ee0a5 --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/prefix/CachedPrefixProvider.java @@ -0,0 +1,37 @@ +package de.kentoj.scrow.bukkit.internal.player.prefix; + +import de.kentoj.scrowlib.player.PlayerPrefixProvider; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; + +import java.io.Closeable; +import java.util.*; + +public class CachedPrefixProvider implements PlayerPrefixProvider { + + private final Map prefixes = new HashMap<>(); + private final List listeners = new ArrayList<>(); + + @Override + public @Nullable Component getPrefix(UUID playerId) { + return prefixes.get(playerId); + } + + @Override + public Closeable onChange(ChangeListener changeListener) { + listeners.add(changeListener); + return () -> listeners.remove(changeListener); + } + + public void setPrefix(UUID playerId, @Nullable Component prefix) { + if (prefix == null) { + prefixes.remove(playerId); + } else { + var oldValue = prefixes.put(playerId, prefix); + var hasChanged = !Objects.equals(oldValue, prefix); + if (hasChanged) { + listeners.forEach(l -> l.onChange(playerId, prefix)); + } + } + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/prefix/LuckPermsPrefixSetter.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/prefix/LuckPermsPrefixSetter.java new file mode 100644 index 0000000..cf6ccb7 --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/internal/player/prefix/LuckPermsPrefixSetter.java @@ -0,0 +1,65 @@ +package de.kentoj.scrow.bukkit.internal.player.prefix; + +import lombok.RequiredArgsConstructor; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.luckperms.api.LuckPerms; +import net.luckperms.api.event.user.UserDataRecalculateEvent; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +@RequiredArgsConstructor +public class LuckPermsPrefixSetter implements Listener { + + private static final MiniMessage MM = MiniMessage.miniMessage(); + + private final LuckPerms luckPerms; + private final CachedPrefixProvider cache; + + @SuppressWarnings("resource") + public void init(Plugin plugin) { + luckPerms.getEventBus().subscribe(UserDataRecalculateEvent.class, this::onDataChange); + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + private void onDataChange(UserDataRecalculateEvent ev) { + var playerId = ev.getUser().getUniqueId(); + if (Bukkit.getPlayer(playerId) == null) return; + + var prefix = ev.getData().getMetaData().getPrefix(); + updatePrefix(playerId, prefix); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) + public void onPlayerJoin(PlayerJoinEvent ev) { + var playerId = ev.getPlayer().getUniqueId(); + var user = luckPerms.getUserManager().getUser(playerId); + if (user == null) return; + + var prefix = user.getCachedData().getMetaData().getPrefix(); + updatePrefix(playerId, prefix); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent ev) { + var playerId = ev.getPlayer().getUniqueId(); + cache.setPrefix(playerId, (Component) null); + } + + private void updatePrefix(UUID playerId, @Nullable String rawPrefix) { + if (rawPrefix == null) { + cache.setPrefix(playerId, (Component) null); + return; + } + var prefixComponent = MM.deserialize(rawPrefix); + cache.setPrefix(playerId, prefixComponent); + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/ChatStyleListener.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/ChatStyleListener.java new file mode 100644 index 0000000..df03fff --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/ChatStyleListener.java @@ -0,0 +1,23 @@ +package de.kentoj.scrow.bukkit.style; + +import de.kentoj.scrowlib.player.PlayerPrefixProvider; +import io.papermc.paper.event.player.AsyncChatEvent; +import lombok.RequiredArgsConstructor; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +@RequiredArgsConstructor +public class ChatStyleListener implements Listener { + + private final PlayerPrefixProvider prefixProvider; + + @EventHandler + public void onChat(AsyncChatEvent ev) { + var prefix = prefixProvider.getPrefix(ev.getPlayer().getUniqueId()); + Component formattedMessage = StyleHelper.formatMessage(ev.getPlayer().name(), prefix, ev.message()); + ev.setCancelled(true); + Bukkit.broadcast(formattedMessage); + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/StyleHelper.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/StyleHelper.java new file mode 100644 index 0000000..712c326 --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/StyleHelper.java @@ -0,0 +1,26 @@ +package de.kentoj.scrow.bukkit.style; + +import de.kentoj.scrowlib.utils.ComponentUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.jetbrains.annotations.Nullable; + +@NoArgsConstructor(access = AccessLevel.NONE) +public class StyleHelper { + public static Component formatName(Component playerName, @Nullable Component prefix) { + Component result = prefix != null + ? prefix.append(Component.text("│ ").color(NamedTextColor.DARK_GRAY)) + : Component.empty(); + return result.append(playerName.color(NamedTextColor.GRAY)); + } + + public static Component formatMessage(Component playerName, @Nullable Component prefix, Component message) { + Component result = prefix != null + ? prefix.append(Component.text("│ ", NamedTextColor.DARK_GRAY)) + : Component.empty(); + return result.append(playerName.color(NamedTextColor.GRAY).append(Component.text(": "))) + .append(ComponentUtils.resolveURLS(message).colorIfAbsent(NamedTextColor.GRAY)); + } +} diff --git a/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/TabStyleListener.java b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/TabStyleListener.java new file mode 100644 index 0000000..0a798df --- /dev/null +++ b/core-bukkit-impl/src/main/java/de/kentoj/scrow/bukkit/style/TabStyleListener.java @@ -0,0 +1,37 @@ +package de.kentoj.scrow.bukkit.style; + +import de.kentoj.scrowlib.player.PlayerPrefixProvider; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public class TabStyleListener implements Listener { + + private final PlayerPrefixProvider prefixProvider; + + public TabStyleListener(PlayerPrefixProvider prefixProvider) { + this.prefixProvider = prefixProvider; + + //noinspection resource + prefixProvider.onChange(this::onPrefixChange); + } + + private void onPrefixChange(UUID playerID, @Nullable Component prefix) { + var player = Bukkit.getPlayer(playerID); + if (player == null) return; + Component formattedName = StyleHelper.formatName(player.name(), prefix); + player.playerListName(formattedName); + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerJoin(PlayerJoinEvent ev) { + var prefix = prefixProvider.getPrefix(ev.getPlayer().getUniqueId()); + Component formattedName = StyleHelper.formatName(ev.getPlayer().name(), prefix); + ev.getPlayer().playerListName(formattedName); + } +} diff --git a/core-lib/src/main/java/de/kentoj/scrowlib/player/PlayerPrefixProvider.java b/core-lib/src/main/java/de/kentoj/scrowlib/player/PlayerPrefixProvider.java new file mode 100644 index 0000000..795c245 --- /dev/null +++ b/core-lib/src/main/java/de/kentoj/scrowlib/player/PlayerPrefixProvider.java @@ -0,0 +1,18 @@ +package de.kentoj.scrowlib.player; + +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; + +import java.io.Closeable; +import java.util.UUID; + +public interface PlayerPrefixProvider { + + @Nullable Component getPrefix(UUID playerId); + + Closeable onChange(ChangeListener onChange); + + interface ChangeListener { + void onChange(UUID playerId, @Nullable Component newPrefix); + } +}