diff --git a/api/src/main/java/net/momirealms/customnameplates/api/manager/BubbleManager.java b/api/src/main/java/net/momirealms/customnameplates/api/manager/BubbleManager.java index d0a1780..95405e0 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/manager/BubbleManager.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/manager/BubbleManager.java @@ -18,6 +18,7 @@ package net.momirealms.customnameplates.api.manager; import net.momirealms.customnameplates.api.mechanic.bubble.Bubble; +import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider; import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable; @@ -26,6 +27,21 @@ import java.util.List; public interface BubbleManager { + /** + * Set a custom chat provider + * + * @param provider provider + * @return success or not + */ + boolean setCustomChatProvider(AbstractChatProvider provider); + + /** + * Remove a custom chat provider + * + * @return success or not + */ + boolean removeCustomChatProvider(); + /** * Register a bubble into map * @@ -118,6 +134,8 @@ public interface BubbleManager { */ String getDefaultBubble(); + void onChat(Player player, String text, String channel); + /** * Get all the bubbles' keys * diff --git a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/ChannelMode.java b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/ChannelMode.java new file mode 100644 index 0000000..098d7bc --- /dev/null +++ b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/ChannelMode.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customnameplates.api.mechanic.bubble; + +public enum ChannelMode { + + ALL, + JOINED, + CAN_JOIN +} diff --git a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/listener/AbstractChatListener.java b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/provider/AbstractChatProvider.java similarity index 71% rename from api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/listener/AbstractChatListener.java rename to api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/provider/AbstractChatProvider.java index d7b6677..0c90122 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/listener/AbstractChatListener.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/bubble/provider/AbstractChatProvider.java @@ -15,20 +15,25 @@ * along with this program. If not, see . */ -package net.momirealms.customnameplates.api.mechanic.bubble.listener; +package net.momirealms.customnameplates.api.mechanic.bubble.provider; import net.momirealms.customnameplates.api.manager.BubbleManager; +import org.bukkit.entity.Player; import org.bukkit.event.Listener; -public abstract class AbstractChatListener implements Listener { +public abstract class AbstractChatProvider implements Listener { protected BubbleManager chatBubblesManager; - public AbstractChatListener(BubbleManager chatBubblesManager) { + public AbstractChatProvider(BubbleManager chatBubblesManager) { this.chatBubblesManager = chatBubblesManager; } public abstract void register(); public abstract void unregister(); + + public abstract boolean hasJoinedChannel(Player player, String channelID); + + public abstract boolean canJoinChannel(Player player, String channelID); } diff --git a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/misc/ViewerText.java b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/misc/ViewerText.java index c1365a7..f802cd9 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/misc/ViewerText.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/misc/ViewerText.java @@ -44,9 +44,11 @@ public class ViewerText { for (String placeholder : placeholders) { processedText = processedText.replace(placeholder, "%s"); if (placeholder.startsWith("%viewer_")) { - this.placeholders[i] = new ClaimedText(null, "%" + placeholder.substring("%viewer_".length())); + this.placeholders[i] = new ClaimedText(null, "%" + placeholder.substring("%viewer_".length()), false); + } else if (placeholder.startsWith("%rel_")) { + this.placeholders[i] = new ClaimedText(owner, placeholder, true); } else { - this.placeholders[i] = new ClaimedText(owner, placeholder); + this.placeholders[i] = new ClaimedText(owner, placeholder, false); } i++; } @@ -109,11 +111,13 @@ public class ViewerText { private final String placeholder; private final Player owner; private String latestValue; + private final boolean relational; - public ClaimedText(Player owner, String placeholder) { + public ClaimedText(Player owner, String placeholder, boolean relational) { this.placeholder = placeholder; this.owner = owner; this.latestValue = null; + this.relational = relational; this.update(); } @@ -125,7 +129,13 @@ public class ViewerText { public String getValue(Player viewer) { return Objects.requireNonNullElseGet( latestValue, - () -> PlaceholderAPI.setPlaceholders(owner == null ? viewer : owner, placeholder) + () -> { + if (relational) { + return PlaceholderAPI.setRelationalPlaceholders(viewer, owner, placeholder); + } else { + return PlaceholderAPI.setPlaceholders(owner == null ? viewer : owner, placeholder); + } + } ); } } diff --git a/build.gradle.kts b/build.gradle.kts index d832830..de8eac5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { allprojects { - version = "2.3.2.0" + version = "2.3.2.1" apply() apply(plugin = "java") diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/BubbleManagerImpl.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/BubbleManagerImpl.java index 68387cb..3fd8b0a 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/BubbleManagerImpl.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/BubbleManagerImpl.java @@ -25,7 +25,8 @@ import net.momirealms.customnameplates.api.event.BubblesSpawnEvent; import net.momirealms.customnameplates.api.event.NameplateDataLoadEvent; import net.momirealms.customnameplates.api.manager.BubbleManager; import net.momirealms.customnameplates.api.mechanic.bubble.Bubble; -import net.momirealms.customnameplates.api.mechanic.bubble.listener.AbstractChatListener; +import net.momirealms.customnameplates.api.mechanic.bubble.ChannelMode; +import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider; import net.momirealms.customnameplates.api.mechanic.character.CharacterArranger; import net.momirealms.customnameplates.api.mechanic.character.ConfiguredChar; import net.momirealms.customnameplates.api.mechanic.tag.unlimited.EntityTagPlayer; @@ -38,7 +39,7 @@ import net.momirealms.customnameplates.paper.adventure.AdventureManagerImpl; import net.momirealms.customnameplates.paper.mechanic.bubble.image.ImageParser; import net.momirealms.customnameplates.paper.mechanic.bubble.image.ItemsAdderImageImpl; import net.momirealms.customnameplates.paper.mechanic.bubble.image.OraxenImageImpl; -import net.momirealms.customnameplates.paper.mechanic.bubble.listener.*; +import net.momirealms.customnameplates.paper.mechanic.bubble.provider.*; import net.momirealms.customnameplates.paper.setting.CNConfig; import org.bukkit.Bukkit; import org.bukkit.GameMode; @@ -46,6 +47,8 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; import org.bukkit.plugin.PluginManager; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.Nullable; @@ -54,9 +57,10 @@ import java.io.File; import java.util.*; import java.util.concurrent.TimeUnit; -public class BubbleManagerImpl implements BubbleManager { +public class BubbleManagerImpl implements BubbleManager, Listener { - private AbstractChatListener chatListener; + private AbstractChatProvider chatProvider; + private AbstractChatProvider customProvider; private ImageParser imageParser; private final HashMap bubbleMap; private final CustomNameplatesPluginImpl plugin; @@ -73,6 +77,7 @@ public class BubbleManagerImpl implements BubbleManager { private int lengthPerLine; private int subStringIndex; private String[] blacklistChannels; + private ChannelMode channelMode; public BubbleManagerImpl(CustomNameplatesPluginImpl plugin) { this.plugin = plugin; @@ -88,14 +93,16 @@ public class BubbleManagerImpl implements BubbleManager { if (!CNConfig.bubbleModule) return; this.loadConfig(); this.loadBubbles(); - this.registerListener(); + this.registerChatProvider(); this.registerImageParser(); + Bukkit.getPluginManager().registerEvents(this, plugin); } public void unload() { this.imageParser = null; this.bubbleMap.clear(); - if (chatListener != null) chatListener.unregister(); + if (chatProvider != null) chatProvider.unregister(); + HandlerList.unregisterAll(this); } private void loadConfig() { @@ -113,6 +120,7 @@ public class BubbleManagerImpl implements BubbleManager { lengthPerLine = config.getInt("characters-per-line", 30); startFormat = config.getString("default-format.start", ""); endFormat = config.getString("default-format.end", ""); + channelMode = ChannelMode.valueOf(config.getString("channel-mode","all").toUpperCase(Locale.ENGLISH)); } private void registerImageParser() { @@ -124,24 +132,47 @@ public class BubbleManagerImpl implements BubbleManager { } } - private void registerListener() { - if (CNConfig.trChatChannel) { - this.chatListener = new TrChatListener(this); + private void registerChatProvider() { + if (this.customProvider != null) { + this.chatProvider = customProvider; + } else if (CNConfig.trChatChannel) { + this.chatProvider = new TrChatProvider(this); } else if (CNConfig.ventureChatChannel) { - this.chatListener = new VentureChatListener(this); + this.chatProvider = new VentureChatProvider(this); } else if (CNConfig.huskChatChannel) { - this.chatListener = new HuskChatListener(this); + this.chatProvider = new HuskChatProvider(this); } else if (CNConfig.carbonChatChannel) { - this.chatListener = new CarbonChatListener(this); + this.chatProvider = new CarbonChatProvider(this); } else { try { Class.forName("io.papermc.paper.event.player.AsyncChatEvent"); - this.chatListener = new PaperAsyncChatListener(this); + this.chatProvider = new PaperAsyncChatProvider(this); } catch (ClassNotFoundException e) { - this.chatListener = new AsyncChatListener(this); + this.chatProvider = new AsyncChatProvider(this); } } - this.chatListener.register(); + this.chatProvider.register(); + } + + @Override + public boolean setCustomChatProvider(AbstractChatProvider provider) { + if (this.customProvider != null) + return false; + this.customProvider = provider; + if (chatProvider != null) chatProvider.unregister(); + this.registerChatProvider(); + return true; + } + + @Override + public boolean removeCustomChatProvider() { + if (this.customProvider != null) { + this.customProvider.unregister(); + this.customProvider = null; + this.registerChatProvider(); + return true; + } + return false; } private void loadBubbles() { @@ -214,7 +245,13 @@ public class BubbleManagerImpl implements BubbleManager { return this.bubbleMap.remove(key) != null; } + @Override public void onChat(Player player, String text) { + onChat(player, text, null); + } + + @Override + public void onChat(Player player, String text, String channel) { if ( player.getGameMode() == GameMode.SPECTATOR || player.hasPotionEffect(PotionEffectType.INVISIBILITY) || !player.hasPermission("bubbles.use") @@ -270,14 +307,14 @@ public class BubbleManagerImpl implements BubbleManager { int finalIndex = i; String finalBubble = bubble; plugin.getScheduler().runTaskAsyncLater( - () -> sendBubble(player, split[finalIndex], bubbleConfig, finalBubble), + () -> sendBubble(player, split[finalIndex], bubbleConfig, finalBubble, channel), (long) i * 250 + 100, TimeUnit.MILLISECONDS ); } } - private void sendBubble(Player player, String text, Bubble bubbleConfig, String key) { + private void sendBubble(Player player, String text, Bubble bubbleConfig, String key, @Nullable String channel) { if (key.equals("none")) { text = startFormat + PlaceholderAPI.setPlaceholders(player, prefix) + text + PlaceholderAPI.setPlaceholders(player, suffix) + endFormat; } else { @@ -291,7 +328,20 @@ public class BubbleManagerImpl implements BubbleManager { StaticTextEntity entity = tagPlayer.addTag(StaticTextTagSetting.builder() .leaveRule((p, e) -> true) - .comeRule((p, e) -> true) + .comeRule((p, e) -> { + switch (channelMode) { + case ALL -> { + return true; + } + case JOINED -> { + return channel == null || chatProvider.hasJoinedChannel(p, channel); + } + case CAN_JOIN -> { + return channel == null || chatProvider.canJoinChannel(p, channel); + } + } + return false; + }) .verticalOffset(yOffset) .defaultText(text) .plugin("bubble") diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/AsyncChatListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/AsyncChatProvider.java similarity index 71% rename from paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/AsyncChatListener.java rename to paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/AsyncChatProvider.java index 23b3b3c..29892a0 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/AsyncChatListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/AsyncChatProvider.java @@ -15,19 +15,20 @@ * along with this program. If not, see . */ -package net.momirealms.customnameplates.paper.mechanic.bubble.listener; +package net.momirealms.customnameplates.paper.mechanic.bubble.provider; import net.momirealms.customnameplates.api.CustomNameplatesPlugin; import net.momirealms.customnameplates.api.manager.BubbleManager; -import net.momirealms.customnameplates.api.mechanic.bubble.listener.AbstractChatListener; +import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.player.AsyncPlayerChatEvent; -public class AsyncChatListener extends AbstractChatListener { +public class AsyncChatProvider extends AbstractChatProvider { - public AsyncChatListener(BubbleManager chatBubblesManager) { + public AsyncChatProvider(BubbleManager chatBubblesManager) { super(chatBubblesManager); } @@ -41,6 +42,17 @@ public class AsyncChatListener extends AbstractChatListener { HandlerList.unregisterAll(this); } + @Override + public boolean hasJoinedChannel(Player player, String channelID) { + return true; + } + + @Override + public boolean canJoinChannel(Player player, String channelID) { + return true; + } + + // This event is not async sometimes @EventHandler (ignoreCancelled = true) public void onChat(AsyncPlayerChatEvent event) { CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> chatBubblesManager.onChat(event.getPlayer(), event.getMessage())); diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/CarbonChatListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/CarbonChatProvider.java similarity index 58% rename from paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/CarbonChatListener.java rename to paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/CarbonChatProvider.java index 8ff1d1b..918468b 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/CarbonChatListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/CarbonChatProvider.java @@ -15,16 +15,21 @@ * along with this program. If not, see . */ -package net.momirealms.customnameplates.paper.mechanic.bubble.listener; +package net.momirealms.customnameplates.paper.mechanic.bubble.provider; import net.draycia.carbon.api.CarbonChat; -import net.draycia.carbon.api.CarbonChatProvider; +import net.draycia.carbon.api.channels.ChannelRegistry; import net.draycia.carbon.api.channels.ChatChannel; import net.draycia.carbon.api.event.CarbonEventSubscription; import net.draycia.carbon.api.event.events.CarbonChatEvent; +import net.draycia.carbon.api.users.CarbonPlayer; +import net.draycia.carbon.paper.CarbonChatPaper; +import net.draycia.carbon.paper.users.CarbonPlayerPaper; +import net.kyori.adventure.key.Key; import net.momirealms.customnameplates.api.CustomNameplatesPlugin; import net.momirealms.customnameplates.api.manager.BubbleManager; -import net.momirealms.customnameplates.api.mechanic.bubble.listener.AbstractChatListener; +import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider; +import net.momirealms.customnameplates.api.util.LogUtils; import net.momirealms.customnameplates.paper.util.ReflectionUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -32,19 +37,21 @@ import org.bukkit.entity.Player; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -public class CarbonChatListener extends AbstractChatListener { +public class CarbonChatProvider extends AbstractChatProvider { private final CarbonChat api; private CarbonEventSubscription subscription; private Method originalMessageMethod; private Method channelKeyMethod; + private Method getChannelByKeyMethod; - public CarbonChatListener(BubbleManager chatBubblesManager) { + public CarbonChatProvider(BubbleManager chatBubblesManager) { super(chatBubblesManager); - this.api = CarbonChatProvider.carbonChat(); + this.api = net.draycia.carbon.api.CarbonChatProvider.carbonChat(); try { this.originalMessageMethod = CarbonChatEvent.class.getMethod("originalMessage"); this.channelKeyMethod = ChatChannel.class.getMethod("key"); + this.getChannelByKeyMethod = ChannelRegistry.class.getMethod("channel", ReflectionUtils.getKeyClass()); } catch (Exception e) { e.printStackTrace(); } @@ -67,7 +74,7 @@ public class CarbonChatListener extends AbstractChatListener { return; Object component = getComponentFromEvent(event); String message = ReflectionUtils.getMiniMessageTextFromNonShadedComponent(component); - CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> chatBubblesManager.onChat(player, message)); + CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> chatBubblesManager.onChat(player, message, channel)); }); } @@ -78,6 +85,51 @@ public class CarbonChatListener extends AbstractChatListener { } } + @Override + public boolean hasJoinedChannel(Player player, String channelID) { + CarbonPlayer cPlayer = null; + for (CarbonPlayer carbonPlayer : api.server().players()) { + if (carbonPlayer.uuid().equals(player.getUniqueId())) { + cPlayer = carbonPlayer; + break; + } + } + if (cPlayer == null) { + return false; + } + ChatChannel selectedChannel = cPlayer.selectedChannel(); + if (selectedChannel == null) { + return false; + } + Object key = getChannelKey(selectedChannel); + String str = ReflectionUtils.getKeyAsString(key); + return str.equals(channelID); + } + + @Override + public boolean canJoinChannel(Player player, String channelID) { + ChannelRegistry registry = api.channelRegistry(); + Object key = ReflectionUtils.getKerFromString(channelID); + if (key == null) { + return false; + } + ChatChannel channel = null; + try { + channel = (ChatChannel) getChannelByKeyMethod.invoke(registry, key); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + if (channel == null) { + LogUtils.warn("Channel " + channelID + " doesn't exist."); + return false; + } + String perm = channel.permission(); + if (perm == null) { + return true; + } + return player.hasPermission(perm); + } + private Object getChannelKey(ChatChannel channel) { try { return this.channelKeyMethod.invoke(channel); diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/HuskChatListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/HuskChatProvider.java similarity index 55% rename from paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/HuskChatListener.java rename to paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/HuskChatProvider.java index 9598d07..e57cf3b 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/HuskChatListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/HuskChatProvider.java @@ -15,20 +15,26 @@ * along with this program. If not, see . */ -package net.momirealms.customnameplates.paper.mechanic.bubble.listener; +package net.momirealms.customnameplates.paper.mechanic.bubble.provider; +import me.arasple.mc.trchat.TrChat; +import me.arasple.mc.trchat.api.TrChatAPI; import net.momirealms.customnameplates.api.CustomNameplatesPlugin; import net.momirealms.customnameplates.api.manager.BubbleManager; -import net.momirealms.customnameplates.api.mechanic.bubble.listener.AbstractChatListener; +import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider; +import net.momirealms.customnameplates.api.util.LogUtils; +import net.william278.huskchat.HuskChat; +import net.william278.huskchat.bukkit.BukkitHuskChat; import net.william278.huskchat.bukkit.event.ChatMessageEvent; +import net.william278.huskchat.channel.Channel; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; -public class HuskChatListener extends AbstractChatListener { +public class HuskChatProvider extends AbstractChatProvider { - public HuskChatListener(BubbleManager chatBubblesManager) { + public HuskChatProvider(BubbleManager chatBubblesManager) { super(chatBubblesManager); } @@ -42,6 +48,30 @@ public class HuskChatListener extends AbstractChatListener { HandlerList.unregisterAll(this); } + @Override + public boolean hasJoinedChannel(Player player, String channelID) { + String channel = BukkitHuskChat.getInstance().getPlayerCache().getPlayerChannel(player.getUniqueId()); + if (channel == null) { + LogUtils.warn("Channel " + channelID + " doesn't exist."); + return false; + } + return channel.equals(channelID); + } + + @Override + public boolean canJoinChannel(Player player, String channelID) { + Channel channel = BukkitHuskChat.getInstance().getSettings().getChannels().get(channelID); + if (channel == null) { + LogUtils.warn("Channel " + channelID + " doesn't exist."); + return false; + } + String receivePerm = channel.getReceivePermission(); + if (receivePerm == null) { + return true; + } + return player.hasPermission(receivePerm); + } + @EventHandler (ignoreCancelled = true) public void onHuskChat(ChatMessageEvent event) { String channel = event.getChannelId(); @@ -52,7 +82,7 @@ public class HuskChatListener extends AbstractChatListener { if (player == null || !player.isOnline()) return; CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> { - chatBubblesManager.onChat(player, event.getMessage()); + chatBubblesManager.onChat(player, event.getMessage(), channel); }); } } \ No newline at end of file diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/PaperAsyncChatListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/PaperAsyncChatProvider.java similarity index 80% rename from paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/PaperAsyncChatListener.java rename to paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/PaperAsyncChatProvider.java index 8b5fc00..fb65e53 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/PaperAsyncChatListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/PaperAsyncChatProvider.java @@ -15,25 +15,26 @@ * along with this program. If not, see . */ -package net.momirealms.customnameplates.paper.mechanic.bubble.listener; +package net.momirealms.customnameplates.paper.mechanic.bubble.provider; import io.papermc.paper.event.player.AsyncChatEvent; import net.momirealms.customnameplates.api.CustomNameplatesPlugin; import net.momirealms.customnameplates.api.manager.BubbleManager; -import net.momirealms.customnameplates.api.mechanic.bubble.listener.AbstractChatListener; +import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider; import net.momirealms.customnameplates.paper.util.ReflectionUtils; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -public class PaperAsyncChatListener extends AbstractChatListener { +public class PaperAsyncChatProvider extends AbstractChatProvider { private Method messageMethod; - public PaperAsyncChatListener(BubbleManager chatBubblesManager) { + public PaperAsyncChatProvider(BubbleManager chatBubblesManager) { super(chatBubblesManager); try { this.messageMethod = AsyncChatEvent.class.getMethod("message"); @@ -52,6 +53,16 @@ public class PaperAsyncChatListener extends AbstractChatListener { HandlerList.unregisterAll(this); } + @Override + public boolean hasJoinedChannel(Player player, String channelID) { + return true; + } + + @Override + public boolean canJoinChannel(Player player, String channelID) { + return true; + } + @EventHandler (ignoreCancelled = true) public void onChat(AsyncChatEvent event) { Object component = getComponentFromEvent(event); diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/TrChatListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/TrChatProvider.java similarity index 64% rename from paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/TrChatListener.java rename to paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/TrChatProvider.java index d681c80..461e5b2 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/TrChatListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/TrChatProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customnameplates.paper.mechanic.bubble.listener; +package net.momirealms.customnameplates.paper.mechanic.bubble.provider; import me.arasple.mc.trchat.TrChat; import me.arasple.mc.trchat.api.event.TrChatEvent; @@ -24,16 +24,18 @@ import me.arasple.mc.trchat.module.internal.filter.FilteredObject; import me.arasple.mc.trchat.taboolib.platform.BukkitAdapter; import net.momirealms.customnameplates.api.CustomNameplatesPlugin; import net.momirealms.customnameplates.api.manager.BubbleManager; -import net.momirealms.customnameplates.api.mechanic.bubble.listener.AbstractChatListener; +import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider; +import net.momirealms.customnameplates.api.util.LogUtils; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; -public class TrChatListener extends AbstractChatListener { +public class TrChatProvider extends AbstractChatProvider { private final BukkitAdapter adapter; - public TrChatListener(BubbleManager chatBubblesManager) { + public TrChatProvider(BubbleManager chatBubblesManager) { super(chatBubblesManager); this.adapter = new BukkitAdapter(); } @@ -48,6 +50,27 @@ public class TrChatListener extends AbstractChatListener { HandlerList.unregisterAll(this); } + @Override + public boolean hasJoinedChannel(Player player, String channelID) { + if (TrChat.INSTANCE.api().getChannelManager().getChannel(channelID) instanceof Channel channel) { + return channel.getListeners().contains(player.getName()); + } else { + LogUtils.warn("Channel " + channelID + " doesn't exist."); + return false; + } + } + + @Override + public boolean canJoinChannel(Player player, String channelID) { + if (TrChat.INSTANCE.api().getChannelManager().getChannel(channelID) instanceof Channel channel) { + String perm = channel.getSettings().getJoinPermission(); + return player.hasPermission(perm); + } else { + LogUtils.warn("Channel " + channelID + " doesn't exist."); + return false; + } + } + @EventHandler (ignoreCancelled = true) public void onTrChat(TrChatEvent event) { if (!event.getForward()) return; @@ -58,7 +81,7 @@ public class TrChatListener extends AbstractChatListener { } FilteredObject object = TrChat.INSTANCE.api().getFilterManager().filter(event.getMessage(), adapter.adaptPlayer(event.getPlayer()), true); CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> { - chatBubblesManager.onChat(event.getSession().getPlayer(), object.getFiltered()); + chatBubblesManager.onChat(event.getSession().getPlayer(), object.getFiltered(), channelName); }); } } \ No newline at end of file diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/VentureChatListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/VentureChatProvider.java similarity index 61% rename from paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/VentureChatListener.java rename to paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/VentureChatProvider.java index da63cc7..1574c29 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/listener/VentureChatListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/bubble/provider/VentureChatProvider.java @@ -15,20 +15,24 @@ * along with this program. If not, see . */ -package net.momirealms.customnameplates.paper.mechanic.bubble.listener; +package net.momirealms.customnameplates.paper.mechanic.bubble.provider; +import mineverse.Aust1n46.chat.api.MineverseChatAPI; import mineverse.Aust1n46.chat.api.MineverseChatPlayer; import mineverse.Aust1n46.chat.api.events.VentureChatEvent; +import mineverse.Aust1n46.chat.channel.ChatChannel; import net.momirealms.customnameplates.api.CustomNameplatesPlugin; import net.momirealms.customnameplates.api.manager.BubbleManager; -import net.momirealms.customnameplates.api.mechanic.bubble.listener.AbstractChatListener; +import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider; +import net.momirealms.customnameplates.api.util.LogUtils; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; -public class VentureChatListener extends AbstractChatListener { +public class VentureChatProvider extends AbstractChatProvider { - public VentureChatListener(BubbleManager chatBubblesManager) { + public VentureChatProvider(BubbleManager chatBubblesManager) { super(chatBubblesManager); } @@ -42,6 +46,25 @@ public class VentureChatListener extends AbstractChatListener { HandlerList.unregisterAll(this); } + @Override + public boolean hasJoinedChannel(Player player, String channelID) { + MineverseChatPlayer mcp = MineverseChatAPI.getOnlineMineverseChatPlayer(player); + return mcp.getCurrentChannel().getName().equals(channelID); + } + + @Override + public boolean canJoinChannel(Player player, String channelID) { + ChatChannel channel = ChatChannel.getChannel(channelID); + if (channel == null) { + LogUtils.warn("Channel " + channelID + " doesn't exist."); + return false; + } + if (channel.hasPermission()) { + return player.hasPermission(channel.getPermission()); + } + return true; + } + @EventHandler (ignoreCancelled = true) public void onVentureChat(VentureChatEvent event) { String channelName = event.getChannel().getName(); @@ -53,7 +76,7 @@ public class VentureChatListener extends AbstractChatListener { return; } CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> { - chatBubblesManager.onChat(chatPlayer.getPlayer(), event.getChat()); + chatBubblesManager.onChat(chatPlayer.getPlayer(), event.getChat(), channelName); }); } } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedEntity.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedEntity.java index 3eff896..cbf2c24 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedEntity.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedEntity.java @@ -92,7 +92,9 @@ public class UnlimitedEntity implements EntityTagEntity { } staticTags.add(tag); for (Player all : nearbyPlayers) { - tag.addPlayerToViewers(all); + if (tag.getComeRule().isPassed(all, entity)) { + tag.addPlayerToViewers(all); + } } } @@ -137,7 +139,6 @@ public class UnlimitedEntity implements EntityTagEntity { } } - public void move(Player receiver, short x, short y, short z, boolean onGround) { for (StaticTextEntity tag : staticTags) { tag.move(receiver, x, y, z, onGround); diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedPlayer.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedPlayer.java index 499c696..3b3b2c2 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedPlayer.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedPlayer.java @@ -61,7 +61,9 @@ public class UnlimitedPlayer extends UnlimitedEntity implements EntityTagPlayer } staticTags.add(tag); for (Player all : nearbyPlayers) { - tag.addPlayerToViewers(all); + if (tag.getComeRule().isPassed(all, owner)) { + tag.addPlayerToViewers(all); + } } } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/storage/method/database/nosql/RedisManager.java b/paper/src/main/java/net/momirealms/customnameplates/paper/storage/method/database/nosql/RedisManager.java index 0eaa354..c6256e1 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/storage/method/database/nosql/RedisManager.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/storage/method/database/nosql/RedisManager.java @@ -152,7 +152,6 @@ public class RedisManager extends AbstractStorage { try (Jedis jedis = jedisPool.getResource()) { byte[] key = getRedisKey("cn_data", uuid); byte[] data = jedis.get(key); - jedis.del(key); if (data != null) { future.complete(Optional.of(plugin.getStorageManager().fromBytes(data))); plugin.debug("Redis data retrieved for " + uuid + "; normal data"); diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/storage/method/database/sql/AbstractHikariDatabase.java b/paper/src/main/java/net/momirealms/customnameplates/paper/storage/method/database/sql/AbstractHikariDatabase.java index 29a7fc9..993cdc4 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/storage/method/database/sql/AbstractHikariDatabase.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/storage/method/database/sql/AbstractHikariDatabase.java @@ -55,7 +55,6 @@ public abstract class AbstractHikariDatabase extends AbstractSQLDatabase impleme } else if (getStorageType() == StorageType.MySQL) { try { Class.forName("com.mysql.jdbc.Driver"); - LogUtils.warn("It seems that you are not using MySQL 8.0+. It's recommended to update."); } catch (ClassNotFoundException e2) { LogUtils.warn("No MySQL driver is found"); } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/util/ReflectionUtils.java b/paper/src/main/java/net/momirealms/customnameplates/paper/util/ReflectionUtils.java index 4ab126a..2641b92 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/util/ReflectionUtils.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/util/ReflectionUtils.java @@ -18,6 +18,7 @@ package net.momirealms.customnameplates.paper.util; import com.comphenix.protocol.utility.MinecraftReflection; +import net.kyori.adventure.key.Key; import net.momirealms.customnameplates.api.util.LogUtils; import java.lang.reflect.Constructor; @@ -36,7 +37,9 @@ public class ReflectionUtils { private static Object emptyComponent; private static Method serializeComponentMethod; private static Method keyAsStringMethod; + private static Method keyFromStringMethod; private static Object miniMessageInstance; + private static Class keyClass; public static void load() { try { @@ -63,8 +66,9 @@ public class ReflectionUtils { Method miniMessageInstanceGetMethod = miniMessageClass.getMethod("miniMessage"); miniMessageInstance = miniMessageInstanceGetMethod.invoke(null); serializeComponentMethod = miniMessageClass.getMethod("serialize", componentClass); - Class keyClass = Class.forName("net;kyori;adventure;key;Key".replace(";", ".")); + keyClass = Class.forName("net;kyori;adventure;key;Key".replace(";", ".")); keyAsStringMethod = keyClass.getMethod("asString"); + keyFromStringMethod = keyClass.getMethod("key", String.class); } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) { } @@ -90,6 +94,10 @@ public class ReflectionUtils { return emptyComponent; } + public static Class getKeyClass() { + return keyClass; + } + public static String getKeyAsString(Object key) { try { return (String) keyAsStringMethod.invoke(key); @@ -99,6 +107,15 @@ public class ReflectionUtils { return ""; } + public static Object getKerFromString(String key) { + try { + return keyFromStringMethod.invoke(key); + } catch (InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + public static String getMiniMessageTextFromNonShadedComponent(Object component) { try { return (String) serializeComponentMethod.invoke(miniMessageInstance, component); diff --git a/paper/src/main/resources/configs/bubble.yml b/paper/src/main/resources/configs/bubble.yml index c2cec66..4c18458 100644 --- a/paper/src/main/resources/configs/bubble.yml +++ b/paper/src/main/resources/configs/bubble.yml @@ -3,6 +3,11 @@ blacklist-channels: - Private - Staff +# ALL: all the players can see the bubble +# JOINED: players in the same channel can see each other's bubble +# CAN_JOIN: players that have permission to certain channels would see the bubble in that channel +channel-mode: ALL + # Default bubble to display if player's bubble is "none" default-bubble: 'chat'