diff --git a/api/src/main/java/net/momirealms/customnameplates/api/manager/NameplateManager.java b/api/src/main/java/net/momirealms/customnameplates/api/manager/NameplateManager.java index 0ba45a5..311d128 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/manager/NameplateManager.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/manager/NameplateManager.java @@ -39,6 +39,10 @@ public interface NameplateManager { @NotNull String getDefaultNameplate(); + void handlePlayerJoin(Player player); + + void handlePlayerQuit(Player player); + /** * Put an entity's ID to map * This map is used for quickly getting the entity instance @@ -241,7 +245,7 @@ public interface NameplateManager { * @param key key * @return nameplate */ - @NotNull + @Nullable Nameplate getNameplate(@NotNull String key); /** diff --git a/api/src/main/java/net/momirealms/customnameplates/api/manager/TeamTagManager.java b/api/src/main/java/net/momirealms/customnameplates/api/manager/TeamTagManager.java index 8f55738..c28e0c9 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/manager/TeamTagManager.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/manager/TeamTagManager.java @@ -19,6 +19,7 @@ package net.momirealms.customnameplates.api.manager; import net.momirealms.customnameplates.api.mechanic.tag.team.TeamTagPlayer; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.UUID; @@ -32,7 +33,7 @@ public interface TeamTagManager { * * @return team tag */ - @Nullable + @NotNull TeamTagPlayer createTagForPlayer(Player player, String prefix, String suffix); /** diff --git a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/tag/unlimited/DynamicTextEntity.java b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/tag/unlimited/DynamicTextEntity.java index 61b8455..8d16841 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/tag/unlimited/DynamicTextEntity.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/tag/unlimited/DynamicTextEntity.java @@ -49,6 +49,8 @@ public interface DynamicTextEntity { void setSneak(boolean sneaking, boolean respawn); + void updateVisibility(); + void removePlayerFromViewers(Player player); void addPlayerToViewers(Player player); diff --git a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/tag/unlimited/StaticTextEntity.java b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/tag/unlimited/StaticTextEntity.java index fd85347..fe9b456 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/mechanic/tag/unlimited/StaticTextEntity.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/mechanic/tag/unlimited/StaticTextEntity.java @@ -73,4 +73,6 @@ public interface StaticTextEntity { UUID getUUID(); void handlePose(Pose previous, Pose pose); + + void setSneak(boolean sneaking, boolean onGround); } diff --git a/build.gradle.kts b/build.gradle.kts index eaf919a..85d4edb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { allprojects { - version = "2.3.3.1" + version = "2.3.3.2" 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 5df1a56..9ade5fc 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 @@ -18,20 +18,24 @@ package net.momirealms.customnameplates.paper.mechanic.bubble; import me.clip.placeholderapi.PlaceholderAPI; +import me.libraryaddict.disguise.DisguiseAPI; import net.kyori.adventure.text.minimessage.MiniMessage; import net.momirealms.customnameplates.api.CustomNameplatesPlugin; import net.momirealms.customnameplates.api.data.OnlineUser; 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.manager.RequirementManager; import net.momirealms.customnameplates.api.mechanic.bubble.Bubble; 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; +import net.momirealms.customnameplates.api.mechanic.tag.unlimited.EntityTagEntity; import net.momirealms.customnameplates.api.mechanic.tag.unlimited.StaticTextEntity; import net.momirealms.customnameplates.api.mechanic.tag.unlimited.StaticTextTagSetting; +import net.momirealms.customnameplates.api.requirement.Condition; +import net.momirealms.customnameplates.api.requirement.Requirement; import net.momirealms.customnameplates.api.util.FontUtils; import net.momirealms.customnameplates.api.util.LogUtils; import net.momirealms.customnameplates.paper.CustomNameplatesPluginImpl; @@ -43,18 +47,19 @@ import net.momirealms.customnameplates.paper.mechanic.bubble.provider.*; import net.momirealms.customnameplates.paper.setting.CNConfig; import net.momirealms.customnameplates.paper.util.DisguiseUtils; import org.bukkit.Bukkit; -import org.bukkit.GameMode; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Entity; 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; import java.io.File; +import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; @@ -79,6 +84,7 @@ public class BubbleManagerImpl implements BubbleManager, Listener { private int subStringIndex; private String[] blacklistChannels; private ChannelMode channelMode; + private Requirement[] requirements; public BubbleManagerImpl(CustomNameplatesPluginImpl plugin) { this.plugin = plugin; @@ -108,6 +114,7 @@ public class BubbleManagerImpl implements BubbleManager, Listener { private void loadConfig() { YamlConfiguration config = plugin.getConfig("configs" + File.separator + "bubble.yml"); + updateConfigFile(config); defaultBubble = config.getString("default-bubbles", "chat"); prefix = config.getString("text-prefix", ""); suffix = config.getString("text-suffix", ""); @@ -122,6 +129,22 @@ public class BubbleManagerImpl implements BubbleManager, Listener { startFormat = config.getString("default-format.start", ""); endFormat = config.getString("default-format.end", ""); channelMode = ChannelMode.valueOf(config.getString("channel-mode","all").toUpperCase(Locale.ENGLISH)); + requirements = plugin.getRequirementManager().getRequirements(config.getConfigurationSection("requirements")); + } + + private void updateConfigFile(YamlConfiguration config) { + try { + if (!config.contains("requirements")) { + ConfigurationSection section = config.createSection("requirements"); + section.set("!gamemode", "spectator"); + section.set("permission", "bubbles.use"); + section.set("self-disguised", false); + section.set("potion-effect", "INVISIBILITY<0"); + config.save(new File(plugin.getDataFolder(), "configs" + File.separator + "bubble.yml")); + } + } catch (IOException e) { + e.printStackTrace(); + } } private void registerImageParser() { @@ -253,12 +276,7 @@ public class BubbleManagerImpl implements BubbleManager, Listener { @Override public void onChat(Player player, String text, String channel) { - if ( player.getGameMode() == GameMode.SPECTATOR - || player.hasPotionEffect(PotionEffectType.INVISIBILITY) - || !player.hasPermission("bubbles.use") - ) return; - - if (CNConfig.hasLibsDisguise && DisguiseUtils.isDisguised(player)) { + if (!RequirementManager.isRequirementMet(new Condition(player), requirements)) { return; } @@ -327,11 +345,12 @@ public class BubbleManagerImpl implements BubbleManager, Listener { int width = FontUtils.getTextWidth(text); text = bubbleConfig.getPrefixWithFont(width) + text + bubbleConfig.getSuffixWithFont(width); } - EntityTagPlayer tagPlayer = plugin.getNameplateManager().getUnlimitedTagManager().createOrGetTagForPlayer(player); - if (tagPlayer == null) + + EntityTagEntity tagEntity = plugin.getNameplateManager().getUnlimitedTagManager().createOrGetTagForEntity(player); + if (tagEntity == null) return; - StaticTextEntity entity = tagPlayer.addTag(StaticTextTagSetting.builder() + StaticTextEntity entity = tagEntity.addTag(StaticTextTagSetting.builder() .leaveRule((p, e) -> true) .comeRule((p, e) -> { switch (channelMode) { @@ -352,14 +371,14 @@ public class BubbleManagerImpl implements BubbleManager, Listener { .plugin("bubble") .build()); - for (StaticTextEntity bubble : tagPlayer.getStaticTags()) { + for (StaticTextEntity bubble : tagEntity.getStaticTags()) { if (bubble.getPlugin().equals("bubble")) { bubble.setOffset(bubble.getOffset() + lineSpace); } } plugin.getScheduler().runTaskAsyncLater(() -> { - tagPlayer.removeTag(entity); + tagEntity.removeTag(entity); }, stayTime, TimeUnit.SECONDS); } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/NameplateManagerImpl.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/NameplateManagerImpl.java index 456b42c..ad44906 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/NameplateManagerImpl.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/NameplateManagerImpl.java @@ -51,10 +51,13 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityPoseChangeEvent; +import org.bukkit.event.entity.EntityPotionEffectEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; +import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.*; @@ -80,6 +83,8 @@ public class NameplateManagerImpl implements NameplateManager, Listener { private final EntityMoveListener entityMoveListener; private final EntityLookListener entityLookListener; private final EntityTeleportListener entityTeleportListener; + private final EntityAddEffectListener entityAddEffectListener; + private final EntityRemoveEffectListener entityRemoveEffectListener; /** * Configs @@ -112,6 +117,8 @@ public class NameplateManagerImpl implements NameplateManager, Listener { this.entitySpawnListener = new EntitySpawnListener(this); this.entityLookListener = new EntityLookListener(this); this.entityMoveListener = new EntityMoveListener(this); + this.entityAddEffectListener = new EntityAddEffectListener(this); + this.entityRemoveEffectListener = new EntityRemoveEffectListener(this); } public void reload() { @@ -134,6 +141,8 @@ public class NameplateManagerImpl implements NameplateManager, Listener { ProtocolLibrary.getProtocolManager().removePacketListener(entityLookListener); ProtocolLibrary.getProtocolManager().removePacketListener(entityMoveListener); ProtocolLibrary.getProtocolManager().removePacketListener(entityTeleportListener); + ProtocolLibrary.getProtocolManager().removePacketListener(entityAddEffectListener); + ProtocolLibrary.getProtocolManager().removePacketListener(entityRemoveEffectListener); } public void disable() { @@ -150,6 +159,8 @@ public class NameplateManagerImpl implements NameplateManager, Listener { ProtocolLibrary.getProtocolManager().addPacketListener(entityLookListener); ProtocolLibrary.getProtocolManager().addPacketListener(entityMoveListener); ProtocolLibrary.getProtocolManager().addPacketListener(entityTeleportListener); + ProtocolLibrary.getProtocolManager().addPacketListener(entityAddEffectListener); + ProtocolLibrary.getProtocolManager().addPacketListener(entityRemoveEffectListener); if (!CNConfig.nameplateModule) return; this.loadConfig(); @@ -285,8 +296,12 @@ public class NameplateManagerImpl implements NameplateManager, Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { - // unlimited part var player = event.getPlayer(); + handlePlayerJoin(player); + } + + @Override + public void handlePlayerJoin(Player player) { this.putEntityIDToMap(player.getEntityId(), player); // nameplate module part @@ -297,14 +312,18 @@ public class NameplateManagerImpl implements NameplateManager, Listener { plugin.getScheduler().runTaskAsyncLater(() -> { if (player.isOnline()) this.createNameTag(player); - }, 200, TimeUnit.MILLISECONDS); + }, 100, TimeUnit.MILLISECONDS); } } @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { - // unlimited part var player = event.getPlayer(); + handlePlayerQuit(player); + } + + @Override + public void handlePlayerQuit(Player player) { this.removeEntityIDFromMap(player.getEntityId()); this.teamTagManager.handlePlayerQuit(player); this.unlimitedTagManager.handlePlayerQuit(player); @@ -331,6 +350,17 @@ public class NameplateManagerImpl implements NameplateManager, Listener { } } + // TODO: Potion effect packet seems to be only sent to the player who has effect, + // it might be something related to metadata. Using BukkitAPI is not the best choice + // since it might conflict with some potion plugins that based on packets + @EventHandler (ignoreCancelled = true) + public void onPotionEffectChange(EntityPotionEffectEvent event) { + if (event.getModifiedType() == PotionEffectType.INVISIBILITY) { + unlimitedTagManager.handlePotionEffect(event.getEntity(), + event.getAction() == EntityPotionEffectEvent.Action.REMOVED || event.getAction() == EntityPotionEffectEvent.Action.CLEARED); + } + } + @Override public boolean putEntityIDToMap(int entityID, @NotNull Entity entity) { if (this.entityID2EntityMap.containsKey(entityID)) @@ -590,7 +620,7 @@ public class NameplateManagerImpl implements NameplateManager, Listener { return tagMode; } - @NotNull + @Nullable @Override public Nameplate getNameplate(@NotNull String key) { return nameplateMap.get(key); @@ -660,4 +690,12 @@ public class NameplateManagerImpl implements NameplateManager, Listener { public void onEntityTeleport(Player receiver, int entityID, double x, double y, double z, boolean onGround) { unlimitedTagManager.handleEntityTeleportPacket(receiver, entityID, x, y, z, onGround); } + +// public void onEntityRemoveEffect(Player player, int entityID) { +// unlimitedTagManager.handlePotionEffect(player, entityID,true); +// } +// +// public void onEntityAddEffect(Player player, int entityID) { +// unlimitedTagManager.handlePotionEffect(player, entityID,false); +// } } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityAddEffectListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityAddEffectListener.java new file mode 100644 index 0000000..a886361 --- /dev/null +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityAddEffectListener.java @@ -0,0 +1,45 @@ +/* + * 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.paper.mechanic.nameplate.tag.listener; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; +import net.momirealms.customnameplates.api.CustomNameplatesPlugin; +import net.momirealms.customnameplates.paper.mechanic.nameplate.NameplateManagerImpl; + +public class EntityAddEffectListener extends PacketAdapter { + + private final NameplateManagerImpl manager; + + public EntityAddEffectListener(NameplateManagerImpl manager) { + super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_EFFECT); + this.manager = manager; + } + + @Override + public void onPacketSending(PacketEvent event) { +// PacketContainer packet = event.getPacket(); +// System.out.println("添加包"); +// if (packet.getEffectTypes().read(0) == PotionEffectType.INVISIBILITY) { +// System.out.println("是隐身"); +// manager.onEntityAddEffect(event.getPlayer(), packet.getIntegers().read(0)); +// } + } +} diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityDestroyListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityDestroyListener.java index 8d8c6f8..782158d 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityDestroyListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityDestroyListener.java @@ -30,12 +30,13 @@ public class EntityDestroyListener extends PacketAdapter { private final NameplateManagerImpl manager; public EntityDestroyListener(NameplateManagerImpl manager) { - super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGH, PacketType.Play.Server.ENTITY_DESTROY); + super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_DESTROY); this.manager = manager; } @Override public void onPacketSending(PacketEvent event) { + if (event.isCancelled()) return; PacketContainer packet = event.getPacket(); manager.onEntityDestroy(event.getPlayer(), packet.getIntLists().read(0)); } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityLookListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityLookListener.java index 3bc5be2..488593e 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityLookListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityLookListener.java @@ -30,12 +30,13 @@ public class EntityLookListener extends PacketAdapter { private final NameplateManagerImpl manager; public EntityLookListener(NameplateManagerImpl manager) { - super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.REL_ENTITY_MOVE_LOOK); + super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.REL_ENTITY_MOVE_LOOK); this.manager = manager; } @Override public void onPacketSending(PacketEvent event) { + if (event.isCancelled()) return; PacketContainer packet = event.getPacket(); manager.onEntityMove(event.getPlayer(), packet.getIntegers().read(0), diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityMoveListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityMoveListener.java index 486912c..14f108b 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityMoveListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityMoveListener.java @@ -30,12 +30,13 @@ public class EntityMoveListener extends PacketAdapter { private final NameplateManagerImpl manager; public EntityMoveListener(NameplateManagerImpl manager) { - super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.REL_ENTITY_MOVE); + super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.REL_ENTITY_MOVE); this.manager = manager; } @Override public void onPacketSending(PacketEvent event) { + if (event.isCancelled()) return; PacketContainer packet = event.getPacket(); manager.onEntityMove(event.getPlayer(), packet.getIntegers().read(0), diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityRemoveEffectListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityRemoveEffectListener.java new file mode 100644 index 0000000..8887a88 --- /dev/null +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityRemoveEffectListener.java @@ -0,0 +1,44 @@ +/* + * 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.paper.mechanic.nameplate.tag.listener; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; +import net.momirealms.customnameplates.api.CustomNameplatesPlugin; +import net.momirealms.customnameplates.paper.mechanic.nameplate.NameplateManagerImpl; + +public class EntityRemoveEffectListener extends PacketAdapter { + + private final NameplateManagerImpl manager; + + public EntityRemoveEffectListener(NameplateManagerImpl manager) { + super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.REMOVE_ENTITY_EFFECT); + this.manager = manager; + } + + @Override + public void onPacketSending(PacketEvent event) { +// if (event.isCancelled()) return; +// PacketContainer packet = event.getPacket(); +// if (packet.getEffectTypes().read(0) == PotionEffectType.INVISIBILITY) { +// manager.onEntityRemoveEffect(event.getPlayer(), packet.getIntegers().read(0)); +// } + } +} diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntitySpawnListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntitySpawnListener.java index acfdc06..8c04ddb 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntitySpawnListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntitySpawnListener.java @@ -29,12 +29,13 @@ public class EntitySpawnListener extends PacketAdapter { private final NameplateManagerImpl manager; public EntitySpawnListener(NameplateManagerImpl manager) { - super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGH, CustomNameplatesPlugin.getInstance().getVersionManager().isVersionNewerThan1_20_R2() ? PacketType.Play.Server.SPAWN_ENTITY : PacketType.Play.Server.NAMED_ENTITY_SPAWN); + super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, CustomNameplatesPlugin.getInstance().getVersionManager().isVersionNewerThan1_20_R2() ? PacketType.Play.Server.SPAWN_ENTITY : PacketType.Play.Server.NAMED_ENTITY_SPAWN); this.manager = manager; } @Override public void onPacketSending(PacketEvent event) { + if (event.isCancelled()) return; manager.onEntitySpawn(event.getPlayer(), event.getPacket().getIntegers().read(0)); } } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityTeleportListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityTeleportListener.java index 428a467..346b58c 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityTeleportListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/EntityTeleportListener.java @@ -30,12 +30,13 @@ public class EntityTeleportListener extends PacketAdapter { private final NameplateManagerImpl manager; public EntityTeleportListener(NameplateManagerImpl manager) { - super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.ENTITY_TELEPORT); + super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_TELEPORT); this.manager = manager; } @Override public void onPacketSending(PacketEvent event) { + if (event.isCancelled()) return; PacketContainer packet = event.getPacket(); manager.onEntityTeleport( event.getPlayer(), diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/MagicCosmeticsListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/MagicCosmeticsListener.java index a33a00f..c7ba783 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/MagicCosmeticsListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/MagicCosmeticsListener.java @@ -36,7 +36,7 @@ public class MagicCosmeticsListener implements Listener { this.unlimitedTagManager = unlimitedTagManager; } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onChangeCos(CosmeticChangeEquipEvent event) { final Cosmetic cosmetic = event.getNewCosmetic(); final Player player = event.getPlayer(); @@ -48,7 +48,7 @@ public class MagicCosmeticsListener implements Listener { } } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onEnterBlackListWorld(PlayerChangeBlacklistEvent event) { var player = event.getPlayer(); if (unlimitedTagManager.getUnlimitedObject(player.getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) { @@ -67,7 +67,7 @@ public class MagicCosmeticsListener implements Listener { } } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onEquip(CosmeticEquipEvent event) { final Cosmetic cosmetic = event.getCosmetic(); final Player player = event.getPlayer(); @@ -79,7 +79,7 @@ public class MagicCosmeticsListener implements Listener { } } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onUnEquip(CosmeticUnEquipEvent event) { final Player player = event.getPlayer(); if (event.getCosmeticType() == CosmeticType.HAT) { @@ -90,7 +90,7 @@ public class MagicCosmeticsListener implements Listener { } } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onDataLoaded(PlayerDataLoadEvent event) { for (Cosmetic cosmetic : event.getEquippedCosmetics()) { if (cosmetic instanceof Hat hat) { diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/PlayerInfoListener.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/PlayerInfoListener.java index 526c36c..ec894fb 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/PlayerInfoListener.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/listener/PlayerInfoListener.java @@ -38,12 +38,13 @@ public class PlayerInfoListener extends PacketAdapter { private final TeamTagManagerImpl manager; public PlayerInfoListener(TeamTagManagerImpl manager) { - super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.PLAYER_INFO); + super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.PLAYER_INFO); this.manager = manager; } @Override public void onPacketSending(PacketEvent event) { + if (event.isCancelled()) return; PacketContainer packet = event.getPacket(); Set actions = packet.getPlayerInfoActions().read(0); if (!actions.contains(EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME)) diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/team/TeamTagManagerImpl.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/team/TeamTagManagerImpl.java index ba1571e..9954276 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/team/TeamTagManagerImpl.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/team/TeamTagManagerImpl.java @@ -28,6 +28,7 @@ import net.momirealms.customnameplates.paper.mechanic.nameplate.tag.listener.Pla import org.bukkit.Bukkit; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -84,11 +85,12 @@ public class TeamTagManagerImpl implements TeamTagManager { ProtocolLibrary.getProtocolManager().removePacketListener(tabListener); } + @NotNull @Override @SuppressWarnings("DuplicatedCode") public TeamPlayer createTagForPlayer(Player player, String prefix, String suffix) { if (this.teamPlayerMap.containsKey(player.getUniqueId())) { - return null; + return this.teamPlayerMap.get(player.getUniqueId()); } var teamPlayer = new TeamPlayer(this, player, prefix, suffix); diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/DynamicTextEntityImpl.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/DynamicTextEntityImpl.java index be9faaa..2cb8922 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/DynamicTextEntityImpl.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/DynamicTextEntityImpl.java @@ -47,6 +47,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { private final Requirement[] ownerRequirements; private final Requirement[] viewerRequirements; private final Vector viewers; + private Player[] viewerArray; private final int refreshFrequency; private final int checkFrequency; private int checkTimer; @@ -71,10 +72,11 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { this.viewerRequirements = viewerRequirements; this.checkFrequency = checkFrequency; this.refreshFrequency = refreshFrequency; - this.viewers = new Vector<>(); this.ownerCanShow = RequirementManager.isRequirementMet(new Condition(owner.getPlayer()), ownerRequirements); this.destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY); this.destroyPacket.getIntLists().write(0, List.of(entityId)); + this.viewers = new Vector<>(); + this.viewersToArray(); } @Override @@ -116,21 +118,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { checkTimer++; if (checkTimer >= checkFrequency) { checkTimer = 0; - if (!RequirementManager.isRequirementMet(new Condition(owner.getPlayer()), ownerRequirements)) { - ownerCanShow = false; - for (Player all : owner.getNearbyPlayers()) { - removePlayerFromViewers(all); - } - } else { - ownerCanShow = true; - for (Player all : owner.getNearbyPlayers()) { - if (canSee(all)) { - addPlayerToViewers(all); - } else { - removePlayerFromViewers(all); - } - } - } + updateVisibility(); } refreshTimer++; @@ -141,12 +129,32 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { } } + @Override + public void updateVisibility() { + if (!RequirementManager.isRequirementMet(new Condition(owner.getPlayer()), ownerRequirements)) { + ownerCanShow = false; + for (Player all : owner.getNearbyPlayers()) { + removePlayerFromViewers(all); + } + } else { + ownerCanShow = true; + for (Player all : owner.getNearbyPlayers()) { + if (canSee(all)) { + addPlayerToViewers(all); + } else { + removePlayerFromViewers(all); + } + } + } + } + @Override public void removePlayerFromViewers(Player player) { if (!viewers.contains(player)) { return; } this.viewers.remove(player); + viewersToArray(); destroy(player); } @@ -156,6 +164,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { return; } this.viewers.add(player); + viewersToArray(); spawn(player, owner.getPlayer().getPose()); } @@ -168,7 +177,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { public void setOffset(double offset) { if (yOffset == offset) return; yOffset = offset; - for (Player all : viewers) { + for (Player all : viewerArray) { PacketManager.getInstance().send(all, getTeleportPacket(0)); } } @@ -187,18 +196,19 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { @Override public void spawn(Pose pose) { - for (Player all : viewers) { + for (Player all : viewerArray) { spawn(all, pose); } } @Override public void destroy() { - for (Player all : viewers) { + for (Player all : viewerArray) { PacketManager.getInstance().send(all, destroyPacket); } viewerText.clear(); viewers.clear(); + viewersToArray(); } @Override @@ -210,15 +220,15 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { @Override public void teleport(double x, double y, double z, boolean onGround) { PacketContainer packet = getTeleportPacket(x, y, z, onGround); - for (Player all : viewers) { + for (Player all : viewerArray) { PacketManager.getInstance().send(all, packet); } } @Override public void teleport() { - PacketContainer packet = getTeleportPacket(getCorrection(owner.getPlayer().getPose())); - for (Player viewer : viewers) { + PacketContainer packet = getTeleportPacket(getPlayerHeight()); + for (Player viewer : viewerArray) { PacketManager.getInstance().send(viewer, packet); } } @@ -233,7 +243,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { @Override public void setSneak(boolean isSneaking, boolean onGround) { if (!onGround) { - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { PacketManager.getInstance().send(viewer, FakeEntityUtils.getMetaPacket(entityId, viewerText.getLatestValue(viewer), isSneaking)); } } @@ -247,7 +257,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { @Override public void move(short x, short y, short z, boolean onGround) { PacketContainer packet = getMovePacket(x, y, z, onGround); - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { PacketManager.getInstance().send(viewer, packet); } } @@ -268,14 +278,14 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { @Override public void respawn(Pose pose) { - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { respawn(viewer, pose); } } @Override public void updateText() { - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { updateText(viewer); } } @@ -296,7 +306,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { public void handlePose(Pose previous, Pose pose) { // Add delay to prevent the tag from appearing earlier CustomNameplatesPlugin.get().getScheduler().runTaskAsyncLater(() -> { - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { respawn(viewer, pose); } }, 20, TimeUnit.MILLISECONDS); @@ -316,7 +326,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT); packet.getIntegers().write(0, entityId); packet.getDoubles().write(0, x); - packet.getDoubles().write(1, y + owner.getHatOffset() + getCorrection(owner.getPlayer().getPose()) + yOffset); + packet.getDoubles().write(1, y + owner.getHatOffset() + getPlayerHeight() + yOffset); packet.getDoubles().write(2, z); packet.getBooleans().write(0, onGround); return packet; @@ -332,14 +342,14 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { return packet; } - private Location getEntityLocation(double correction) { + private Location getEntityLocation(double playerHeight) { var player = owner.getPlayer(); double x = player.getLocation().getX(); double y = player.getLocation().getY(); double z = player.getLocation().getZ(); y += yOffset; y += owner.getHatOffset(); - y += correction; + y += playerHeight; return new Location(null, x, y, z); } @@ -348,7 +358,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { entityPacket.getModifier().write(0, entityId); entityPacket.getModifier().write(1, uuid); entityPacket.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND); - Location location = getEntityLocation(getCorrection(pose)); + Location location = getEntityLocation(getPlayerHeight()); entityPacket.getDoubles().write(0, location.getX()); entityPacket.getDoubles().write(1, location.getY()); entityPacket.getDoubles().write(2, location.getZ()); @@ -356,13 +366,11 @@ public class DynamicTextEntityImpl implements DynamicTextEntity { return new PacketContainer[] {entityPacket, metaPacket}; } - private double getCorrection(Pose pose) { - return switch (pose) { - case STANDING -> 1.8; - case SNEAKING -> 1.5; - case SLEEPING -> 0.2; - case SWIMMING, FALL_FLYING, SPIN_ATTACK -> 0.55; - default -> 0; - }; + private double getPlayerHeight() { + return owner.getPlayer().getHeight(); + } + + private void viewersToArray() { + viewerArray = viewers.toArray(new Player[0]); } } \ No newline at end of file diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/StaticTextEntityImpl.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/StaticTextEntityImpl.java index 8363eac..d047ad9 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/StaticTextEntityImpl.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/StaticTextEntityImpl.java @@ -42,6 +42,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { private double yOffset; private final int entityId; private final Vector viewers; + private Player[] viewerArray; private final ConcurrentHashMap textCache; private final NearbyRule comeRule; private final NearbyRule leaveRule; @@ -68,6 +69,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { this.plugin = plugin; this.destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY); this.destroyPacket.getIntLists().write(0, List.of(entityId)); + this.viewersToArray(); } @Override @@ -109,6 +111,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { return; } this.viewers.remove(player); + viewersToArray(); destroy(player); } @@ -118,6 +121,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { return; } this.viewers.add(player); + viewersToArray(); spawn(player, owner.getEntity().getPose()); } @@ -130,7 +134,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { public void setOffset(double offset) { if (yOffset == offset) return; yOffset = offset; - for (Player all : viewers) { + for (Player all : viewerArray) { PacketManager.getInstance().send(all, getTeleportPacket()); } } @@ -139,7 +143,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { public void setText(String text) { if (text.equals(defaultText)) return; this.defaultText = text; - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { PacketManager.getInstance().send(viewer, FakeEntityUtils.getMetaPacket(entityId, getText(viewer), owner.getEntity().isSneaking())); } } @@ -174,11 +178,12 @@ public class StaticTextEntityImpl implements StaticTextEntity { @Override public void destroy() { - for (Player all : viewers) { + for (Player all : viewerArray) { PacketManager.getInstance().send(all, destroyPacket); } viewers.clear(); textCache.clear(); + viewersToArray(); } @Override @@ -190,7 +195,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { @Override public void teleport(double x, double y, double z, boolean onGround) { PacketContainer packet = getTeleportPacket(x, y, z, onGround); - for (Player all : viewers) { + for (Player all : viewerArray) { PacketManager.getInstance().send(all, packet); } } @@ -205,7 +210,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { @Override public void teleport() { PacketContainer packet = getTeleportPacket(); - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { PacketManager.getInstance().send(viewer, packet); } } @@ -218,7 +223,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { @Override public void move(short x, short y, short z, boolean onGround) { PacketContainer packet = getMovePacket(x, y, z, onGround); - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { PacketManager.getInstance().send(viewer, packet); } } @@ -239,7 +244,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { @Override public void respawn(Pose pose) { - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { respawn(viewer, pose); } } @@ -253,12 +258,21 @@ public class StaticTextEntityImpl implements StaticTextEntity { public void handlePose(Pose previous, Pose pose) { // Add delay to prevent the tag from appearing earlier CustomNameplatesPlugin.get().getScheduler().runTaskAsyncLater(() -> { - for (Player viewer : viewers) { + for (Player viewer : viewerArray) { respawn(viewer, pose); } }, 20, TimeUnit.MILLISECONDS); } + @Override + public void setSneak(boolean isSneaking, boolean onGround) { + if (!onGround) { + for (Player viewer : viewerArray) { + PacketManager.getInstance().send(viewer, FakeEntityUtils.getMetaPacket(entityId, getText(viewer), isSneaking)); + } + } + } + public PacketContainer getMovePacket(short x, short y, short z, boolean onGround) { PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE); packet.getIntegers().write(0, entityId); @@ -273,7 +287,7 @@ public class StaticTextEntityImpl implements StaticTextEntity { PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT); packet.getIntegers().write(0, entityId); packet.getDoubles().write(0, x); - packet.getDoubles().write(1, y + yOffset); + packet.getDoubles().write(1, y + ((owner instanceof UnlimitedPlayer player) ? player.getHatOffset() : 0) + getCorrection() + yOffset); packet.getDoubles().write(2, z); packet.getBooleans().write(0, onGround); return packet; @@ -295,6 +309,8 @@ public class StaticTextEntityImpl implements StaticTextEntity { double y = entity.getLocation().getY(); double z = entity.getLocation().getZ(); y += yOffset; + if (owner instanceof UnlimitedPlayer player) y += player.getHatOffset(); + y += getCorrection(); return new Location(null, x, y, z); } @@ -305,9 +321,17 @@ public class StaticTextEntityImpl implements StaticTextEntity { entityPacket.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND); Location location = getEntityLocation(); entityPacket.getDoubles().write(0, location.getX()); - entityPacket.getDoubles().write(1, location.getY() + (pose == Pose.SNEAKING ? -0.3 : 0)); + entityPacket.getDoubles().write(1, location.getY()); entityPacket.getDoubles().write(2, location.getZ()); PacketContainer metaPacket = FakeEntityUtils.getMetaPacket(entityId, text, pose == Pose.SNEAKING); return new PacketContainer[] {entityPacket, metaPacket}; } + + private double getCorrection() { + return owner.getEntity().getHeight() - 1.8; + } + + private void viewersToArray() { + viewerArray = viewers.toArray(new Player[0]); + } } \ No newline at end of file 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 7c6a44c..aac1b9b 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 @@ -200,4 +200,22 @@ public class UnlimitedEntity implements EntityTagEntity { protected void playerVectorToArray() { nearbyPlayerArray = nearbyPlayers.toArray(new Player[0]); } + + public void setVisibility(boolean visible) { + if (!visible) { + for (StaticTextEntity tag : staticTagArray) { + for (Player player : nearbyPlayerArray) { + tag.removePlayerFromViewers(player); + } + } + } else { + for (StaticTextEntity tag : staticTagArray) { + for (Player player : nearbyPlayerArray) { + if (tag.getComeRule().isPassed(player, entity)) { + tag.addPlayerToViewers(player); + } + } + } + } + } } 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 ef544be..23881c8 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 @@ -197,6 +197,9 @@ public class UnlimitedPlayer extends UnlimitedEntity implements EntityTagPlayer } public void sneak(boolean sneaking, boolean flying) { + for (StaticTextEntity tag : staticTagArray) { + tag.setSneak(sneaking, !flying); + } for (DynamicTextEntity tag : dynamicTagArray) { tag.setSneak(sneaking, !flying); } @@ -274,6 +277,12 @@ public class UnlimitedPlayer extends UnlimitedEntity implements EntityTagPlayer } } + public void updateVisibility() { + for (DynamicTextEntity tag : dynamicTagArray) { + tag.updateVisibility(); + } + } + private void dynamicTagVectorToArray() { dynamicTagArray = dynamicTags.toArray(new DynamicTextEntity[0]); } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedTagManagerImpl.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedTagManagerImpl.java index 3c1edd8..c4afb1b 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedTagManagerImpl.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/nameplate/tag/unlimited/UnlimitedTagManagerImpl.java @@ -25,8 +25,11 @@ import net.momirealms.customnameplates.api.mechanic.tag.unlimited.*; import net.momirealms.customnameplates.api.scheduler.CancellableTask; import net.momirealms.customnameplates.api.util.LogUtils; import net.momirealms.customnameplates.paper.mechanic.nameplate.tag.listener.MagicCosmeticsListener; +import net.momirealms.customnameplates.paper.setting.CNConfig; +import net.momirealms.customnameplates.paper.util.DisguiseUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.entity.Pose; import org.bukkit.event.HandlerList; @@ -126,6 +129,10 @@ public class UnlimitedTagManagerImpl implements UnlimitedTagManager { @Override public UnlimitedEntity createOrGetTagForEntity(Entity entity) { + if (entity instanceof Player player) { + return createOrGetTagForPlayer(player); + } + final UUID uuid = entity.getUniqueId(); if (this.unlimitedEntityMap.containsKey(uuid)) { return this.unlimitedEntityMap.get(uuid); @@ -169,6 +176,15 @@ public class UnlimitedTagManagerImpl implements UnlimitedTagManager { return unlimitedEntityMap.get(uuid); } + public void handlePotionEffect(Entity entity, boolean visible) { + UnlimitedEntity unlimitedEntity = getUnlimitedObject(entity.getUniqueId()); + if (unlimitedEntity == null) return; + unlimitedEntity.setVisibility(visible); + if (unlimitedEntity instanceof UnlimitedPlayer unlimitedPlayer) { + CustomNameplatesPlugin.get().getScheduler().runTaskAsyncLater(unlimitedPlayer::updateVisibility, 50, TimeUnit.MILLISECONDS); + } + } + public void handleEntitySpawnPacket(Player receiver, int entityId) { Player spawned = manager.getPlayerByEntityID(entityId); if (spawned == null) return; @@ -228,6 +244,14 @@ public class UnlimitedTagManagerImpl implements UnlimitedTagManager { public void handlePlayerSneak(Player sneaker, boolean sneaking, boolean flying) { UnlimitedEntity unlimitedEntity = getUnlimitedObject(sneaker.getUniqueId()); if (!(unlimitedEntity instanceof UnlimitedPlayer unlimitedPlayer)) return; + if ( sneaking + && CNConfig.hasLibsDisguise + && DisguiseUtils.isDisguised(sneaker) + && DisguiseUtils.getDisguisedType(sneaker) != EntityType.PLAYER + ) { + // disguised entities would not sneak + return; + } unlimitedPlayer.sneak(sneaking, flying); } } diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/requirement/RequirementManagerImpl.java b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/requirement/RequirementManagerImpl.java index ce51c4b..3a4195b 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/requirement/RequirementManagerImpl.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/mechanic/requirement/RequirementManagerImpl.java @@ -34,6 +34,7 @@ import net.momirealms.customnameplates.paper.util.DisguiseUtils; import net.momirealms.customnameplates.paper.util.GeyserUtils; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; @@ -126,6 +127,7 @@ public class RequirementManagerImpl implements RequirementManager { this.registerGameModeRequirement(); this.registerGeyserRequirement(); this.registerDisguisedRequirement(); + this.registerDisguisedTypeRequirement(); } /** @@ -338,6 +340,27 @@ public class RequirementManagerImpl implements RequirementManager { }); } + private void registerDisguisedTypeRequirement() { + registerRequirement("disguised-type", (args) -> { + HashSet types = new HashSet<>(ConfigUtils.stringListArgs(args)); + return condition -> { + if (!CNConfig.hasLibsDisguise) return true; + Player player = condition.getOfflinePlayer().getPlayer(); + if (!DisguiseUtils.isDisguised(player)) return false; + return types.contains(DisguiseUtils.getDisguisedType(player).name()); + }; + }); + registerRequirement("!disguised-type", (args) -> { + HashSet types = new HashSet<>(ConfigUtils.stringListArgs(args)); + return condition -> { + if (!CNConfig.hasLibsDisguise) return true; + Player player = condition.getOfflinePlayer().getPlayer(); + if (!DisguiseUtils.isDisguised(player)) return false; + return !types.contains(DisguiseUtils.getDisguisedType(player).name()); + }; + }); + } + private void registerWorldRequirement() { registerRequirement("world", (args) -> { HashSet worlds = new HashSet<>(ConfigUtils.stringListArgs(args)); diff --git a/paper/src/main/java/net/momirealms/customnameplates/paper/util/DisguiseUtils.java b/paper/src/main/java/net/momirealms/customnameplates/paper/util/DisguiseUtils.java index 6ccb4e6..c06d221 100644 --- a/paper/src/main/java/net/momirealms/customnameplates/paper/util/DisguiseUtils.java +++ b/paper/src/main/java/net/momirealms/customnameplates/paper/util/DisguiseUtils.java @@ -18,11 +18,16 @@ package net.momirealms.customnameplates.paper.util; import me.libraryaddict.disguise.DisguiseAPI; -import org.bukkit.entity.Player; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; public class DisguiseUtils { - public static boolean isDisguised(Player player) { - return DisguiseAPI.isSelfDisguised(player); + public static boolean isDisguised(Entity entity) { + return DisguiseAPI.isDisguised(entity); + } + + public static EntityType getDisguisedType(Entity entity) { + return DisguiseAPI.getDisguise(entity).getType().getEntityType(); } } diff --git a/paper/src/main/resources/configs/bubble.yml b/paper/src/main/resources/configs/bubble.yml index 4c18458..2ce72bf 100644 --- a/paper/src/main/resources/configs/bubble.yml +++ b/paper/src/main/resources/configs/bubble.yml @@ -1,3 +1,10 @@ +# Requirements for sending the bubble +requirements: + permission: bubbles.use + self-disguised: false + '!gamemode': spectator + potion-effect: "INVISIBILITY<0" + # blacklist channels blacklist-channels: - Private