From c0be235538f11afdab2d9877b59826cae9ecbf1b Mon Sep 17 00:00:00 2001 From: fullwall Date: Sat, 8 Jul 2023 21:36:04 +0800 Subject: [PATCH] Send an extra headrotation packet since spigot resets head rotation now, make some protocollib methods async, bump avoid-water costs by one block --- .../net/citizensnpcs/ProtocolLibListener.java | 134 ++++++++++++------ .../npc/ai/AStarNavigationStrategy.java | 4 +- .../net/citizensnpcs/trait/MirrorTrait.java | 4 +- .../net/citizensnpcs/trait/RotationTrait.java | 16 ++- .../waypoint/LinearWaypointProvider.java | 3 +- .../main/java/net/citizensnpcs/util/NMS.java | 7 +- .../java/net/citizensnpcs/util/NMSBridge.java | 5 +- .../nms/v1_19_R3/util/NMSImpl.java | 23 ++- .../entity/HorseSkeletonController.java | 2 +- .../v1_20_R1/util/CitizensEntityTracker.java | 3 + .../nms/v1_20_R1/util/NMSImpl.java | 22 ++- 11 files changed, 134 insertions(+), 89 deletions(-) diff --git a/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java b/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java index e07b34ae9..f3e82658c 100644 --- a/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java +++ b/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java @@ -1,18 +1,26 @@ package net.citizensnpcs; +import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.UUID; import java.util.function.Function; +import org.bukkit.Bukkit; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType.Play.Server; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.ListenerOptions; import com.comphenix.protocol.events.ListenerPriority; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; @@ -28,11 +36,16 @@ import com.comphenix.protocol.wrappers.WrappedGameProfile; import com.comphenix.protocol.wrappers.WrappedSignedProperty; import com.comphenix.protocol.wrappers.WrappedWatchableObject; import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.event.NPCAddTraitEvent; +import net.citizensnpcs.api.event.NPCDespawnEvent; +import net.citizensnpcs.api.event.NPCEvent; +import net.citizensnpcs.api.event.NPCSpawnEvent; import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.api.trait.trait.MobType; import net.citizensnpcs.api.util.Messaging; import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.trait.MirrorTrait; @@ -40,10 +53,12 @@ import net.citizensnpcs.trait.RotationTrait; import net.citizensnpcs.trait.RotationTrait.PacketRotationSession; import net.citizensnpcs.util.NMS; -public class ProtocolLibListener { +public class ProtocolLibListener implements Listener { private final Class flagsClass; private final ProtocolManager manager; + private final Map mirrorTraits = Maps.newConcurrentMap(); private final Citizens plugin; + private final Map rotationTraits = Maps.newConcurrentMap(); public ProtocolLibListener(Citizens plugin) { this.plugin = plugin; @@ -51,6 +66,7 @@ public class ProtocolLibListener { flagsClass = MinecraftReflection.getMinecraftClass("RelativeMovement", "world.entity.RelativeMovement", "EnumPlayerTeleportFlags", "PacketPlayOutPosition$EnumPlayerTeleportFlags", "network.protocol.game.PacketPlayOutPosition$EnumPlayerTeleportFlags"); + Bukkit.getPluginManager().registerEvents(this, plugin); manager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.HIGHEST, Server.ENTITY_METADATA) { @Override public void onPacketSending(PacketEvent event) { @@ -98,12 +114,14 @@ public class ProtocolLibListener { } } }); - manager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.HIGHEST, Server.PLAYER_INFO) { + manager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.HIGHEST, Arrays.asList(Server.PLAYER_INFO), + ListenerOptions.ASYNC) { @Override public void onPacketSending(PacketEvent event) { int version = manager.getProtocolVersion(event.getPlayer()); if (version >= 761) { - NMS.onPlayerInfoAdd(event.getPlayer(), event.getPacket().getHandle()); + NMS.onPlayerInfoAdd(event.getPlayer(), event.getPacket().getHandle(), + uuid -> mirrorTraits.get(uuid)); return; } List list = event.getPacket().getPlayerInfoDataLists().readSafely(0); @@ -114,10 +132,7 @@ public class ProtocolLibListener { PlayerInfoData npcInfo = list.get(i); if (npcInfo == null) continue; - NPC npc = CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(npcInfo.getProfile().getUUID()); - if (npc == null || !npc.isSpawned()) - continue; - MirrorTrait trait = npc.getTraitNullable(MirrorTrait.class); + MirrorTrait trait = mirrorTraits.get(npcInfo.getProfile().getUUID()); if (trait == null || !trait.isMirroring(event.getPlayer())) { continue; } @@ -148,46 +163,45 @@ public class ProtocolLibListener { } } }); - manager.addPacketListener( - new PacketAdapter(plugin, ListenerPriority.MONITOR, Server.ENTITY_HEAD_ROTATION, Server.ENTITY_LOOK) { - @Override - public void onPacketSending(PacketEvent event) { - NPC npc = getNPCFromPacket(event); - if (npc == null) - return; + manager.addPacketListener(new PacketAdapter( + plugin, ListenerPriority.MONITOR, Arrays.asList(Server.ENTITY_HEAD_ROTATION, Server.ENTITY_LOOK, + Server.REL_ENTITY_MOVE_LOOK, Server.ENTITY_MOVE_LOOK, Server.POSITION, Server.ENTITY_TELEPORT), + ListenerOptions.ASYNC) { + @Override + public void onPacketSending(PacketEvent event) { + RotationTrait trait = rotationTraits.get(event.getPacket().getIntegers().readSafely(0)); + if (trait == null) + return; - RotationTrait trait = npc.getTraitNullable(RotationTrait.class); - if (trait == null) - return; + PacketRotationSession session = trait.getPacketSession(event.getPlayer()); + if (session == null || !session.isActive()) + return; - PacketRotationSession session = trait.getPacketSession(event.getPlayer()); - if (session == null || !session.isActive()) - return; + PacketContainer packet = event.getPacket(); + PacketType type = event.getPacketType(); + if (type == Server.ENTITY_HEAD_ROTATION) { + packet.getBytes().write(0, degToByte(session.getHeadYaw())); + } else if (type == Server.ENTITY_LOOK) { + packet.getBytes().write(0, degToByte(session.getBodyYaw())); + packet.getBytes().write(1, degToByte(session.getPitch())); + } else if (type == Server.ENTITY_MOVE_LOOK || type == Server.REL_ENTITY_MOVE_LOOK) { + packet.getBytes().write(0, degToByte(session.getBodyYaw())); + packet.getBytes().write(1, degToByte(session.getPitch())); + } else if (type == Server.POSITION) { + StructureModifier> flagsModifier = packet + .getSets(EnumWrappers.getGenericConverter(flagsClass, PlayerTeleportFlag.class)); + Set rel = flagsModifier.read(0); + rel.remove(PlayerTeleportFlag.ZYAW); + rel.remove(PlayerTeleportFlag.ZPITCH); + flagsModifier.write(0, rel); + packet.getFloat().write(0, session.getBodyYaw()); + packet.getFloat().write(1, session.getPitch()); + } - PacketContainer packet = event.getPacket(); - PacketType type = event.getPacketType(); - if (type == Server.ENTITY_HEAD_ROTATION) { - packet.getBytes().write(0, degToByte(session.getHeadYaw())); - } else if (type == Server.ENTITY_LOOK) { - packet.getBytes().write(0, degToByte(session.getBodyYaw())); - packet.getBytes().write(1, degToByte(session.getPitch())); - } else if (type == Server.ENTITY_MOVE_LOOK || type == Server.REL_ENTITY_MOVE_LOOK) { - packet.getBytes().write(0, degToByte(session.getBodyYaw())); - packet.getBytes().write(1, degToByte(session.getPitch())); - } else if (type == Server.POSITION) { - StructureModifier> flagsModifier = packet - .getSets(EnumWrappers.getGenericConverter(flagsClass, PlayerTeleportFlag.class)); - Set rel = flagsModifier.read(0); - rel.remove(PlayerTeleportFlag.ZYAW); - rel.remove(PlayerTeleportFlag.ZPITCH); - flagsModifier.write(0, rel); - packet.getFloat().write(0, session.getBodyYaw()); - packet.getFloat().write(1, session.getPitch()); - } - - session.onPacketOverwritten(); - } - }); + session.onPacketOverwritten(); + Messaging.log("OVERWRITTEN " + type + " " + packet.getHandle()); + } + }); } @@ -214,6 +228,36 @@ public class ProtocolLibListener { return entity instanceof NPCHolder ? ((NPCHolder) entity).getNPC() : null; } + @EventHandler(ignoreCancelled = true) + public void onNPCDespawn(NPCDespawnEvent event) { + rotationTraits.remove(event.getNPC().getEntity().getEntityId()); + mirrorTraits.remove(event.getNPC().getEntity().getUniqueId()); + } + + @EventHandler(ignoreCancelled = true) + public void onNPCSpawn(NPCSpawnEvent event) { + onSpawn(event); + } + + private void onSpawn(NPCEvent event) { + if (event.getNPC().hasTrait(RotationTrait.class)) { + rotationTraits.put(event.getNPC().getEntity().getEntityId(), + event.getNPC().getTraitNullable(RotationTrait.class)); + } + if (event.getNPC().hasTrait(MirrorTrait.class) + && event.getNPC().getOrAddTrait(MobType.class).getType() == EntityType.PLAYER) { + mirrorTraits.put(event.getNPC().getEntity().getUniqueId(), + event.getNPC().getTraitNullable(MirrorTrait.class)); + } + } + + @EventHandler(ignoreCancelled = true) + public void onTraitAdd(NPCAddTraitEvent event) { + if (!event.getNPC().isSpawned()) + return; + onSpawn(event); + } + public enum PlayerTeleportFlag { X, Y, diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java index c6c1cc46c..630e3ae4b 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java @@ -158,10 +158,10 @@ public class AStarNavigationStrategy extends AbstractPathStrategy { @Override public float getCost(BlockSource source, PathPoint point) { Vector pos = point.getVector(); - Material above = source.getMaterialAt(pos.setY(pos.getY() + 1)); + Material above = source.getMaterialAt(pos.getBlockX(), pos.getBlockY() + 1, pos.getBlockZ()); return params.avoidWater() && (MinecraftBlockExaminer.isLiquid(above) || MinecraftBlockExaminer.isLiquidOrInLiquid(pos.toLocation(source.getWorld()).getBlock())) - ? 1F + ? 2F : 0F; } diff --git a/main/src/main/java/net/citizensnpcs/trait/MirrorTrait.java b/main/src/main/java/net/citizensnpcs/trait/MirrorTrait.java index 3dbf74a57..c63f2ca8b 100644 --- a/main/src/main/java/net/citizensnpcs/trait/MirrorTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/MirrorTrait.java @@ -11,9 +11,9 @@ import net.citizensnpcs.api.trait.TraitName; @TraitName("mirrortrait") public class MirrorTrait extends Trait { @Persist - private boolean enabled; + private volatile boolean enabled; @Persist - private boolean mirrorName; + private volatile boolean mirrorName; public MirrorTrait() { super("mirrortrait"); diff --git a/main/src/main/java/net/citizensnpcs/trait/RotationTrait.java b/main/src/main/java/net/citizensnpcs/trait/RotationTrait.java index ec6dac1f2..06f207c8d 100644 --- a/main/src/main/java/net/citizensnpcs/trait/RotationTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/RotationTrait.java @@ -18,6 +18,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.persistence.Persistable; import net.citizensnpcs.api.trait.Trait; @@ -32,7 +33,7 @@ public class RotationTrait extends Trait { private final RotationParams globalParameters = new RotationParams(); private final RotationSession globalSession = new RotationSession(globalParameters); private final List packetSessions = Lists.newArrayList(); - private final Map packetSessionsByUUID = Maps.newHashMap(); + private final Map packetSessionsByUUID = Maps.newConcurrentMap(); public RotationTrait() { super("rotationtrait"); @@ -104,6 +105,9 @@ public class RotationTrait extends Trait { public void run() { if (!npc.isSpawned()) return; + if (npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, false)) { + NMS.setPitch(npc.getEntity(), 0); + } Set ran = Sets.newHashSet(); for (Iterator itr = Iterables.concat(packetSessions, packetSessionsByUUID.values()) @@ -146,9 +150,9 @@ public class RotationTrait extends Trait { } public static class PacketRotationSession { - private boolean ended; + private volatile boolean ended; private final RotationSession session; - private PacketRotationTriple triple; + private volatile PacketRotationTriple triple; public PacketRotationSession(RotationSession session) { this.session = session; @@ -201,9 +205,9 @@ public class RotationTrait extends Trait { } private static class PacketRotationTriple extends EntityRotation { - private float lastBodyYaw; - private float lastHeadYaw; - private float lastPitch; + private volatile float lastBodyYaw; + private volatile float lastHeadYaw; + private volatile float lastPitch; public PacketRotationTriple(Entity entity) { super(entity); diff --git a/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java index c1a8cbfbf..24ea60ae6 100644 --- a/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java +++ b/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java @@ -410,7 +410,8 @@ public class LinearWaypointProvider implements EnumerableWaypointProvider { if (showingMarkers) { markers.createMarker(element, element.getLocation().clone()); } - Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_ADDED_WAYPOINT, formatLoc(at), idx); + Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_ADDED_WAYPOINT, formatLoc(at), + waypoints.size()); } else if (waypoints.size() > 0 && !event.getPlayer().isSneaking()) { event.setCancelled(true); diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index 1d373f6f3..875092fbd 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -7,7 +7,9 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.List; +import java.util.UUID; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -57,6 +59,7 @@ import net.citizensnpcs.npc.ai.MCNavigationStrategy.MCNavigator; import net.citizensnpcs.npc.ai.MCTargetStrategy.TargetNavigator; import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.skin.SkinnableEntity; +import net.citizensnpcs.trait.MirrorTrait; import net.citizensnpcs.trait.PacketNPC; import net.citizensnpcs.trait.versioned.CamelTrait.CamelPose; import net.citizensnpcs.trait.versioned.SnifferTrait.SnifferState; @@ -640,8 +643,8 @@ public class NMS { BRIDGE.mount(entity, passenger); } - public static void onPlayerInfoAdd(Player player, Object source) { - BRIDGE.onPlayerInfoAdd(player, source); + public static void onPlayerInfoAdd(Player player, Object source, Function mirrorTraits) { + BRIDGE.onPlayerInfoAdd(player, source, mirrorTraits); } public static InventoryView openAnvilInventory(Player player, Inventory inventory, String title) { diff --git a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java index 1b5e8ecb4..d2c6186d0 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java +++ b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java @@ -2,6 +2,8 @@ package net.citizensnpcs.util; import java.util.Collection; import java.util.List; +import java.util.UUID; +import java.util.function.Function; import org.bukkit.Location; import org.bukkit.Sound; @@ -40,6 +42,7 @@ import net.citizensnpcs.api.util.EntityDim; import net.citizensnpcs.npc.ai.MCNavigationStrategy.MCNavigator; import net.citizensnpcs.npc.ai.MCTargetStrategy.TargetNavigator; import net.citizensnpcs.npc.skin.SkinnableEntity; +import net.citizensnpcs.trait.MirrorTrait; import net.citizensnpcs.trait.versioned.CamelTrait.CamelPose; import net.citizensnpcs.trait.versioned.SnifferTrait.SnifferState; import net.citizensnpcs.util.EntityPacketTracker.PacketAggregator; @@ -134,7 +137,7 @@ public interface NMSBridge { public void mount(Entity entity, Entity passenger); - public default void onPlayerInfoAdd(Player player, Object source) { + public default void onPlayerInfoAdd(Player player, Object source, Function mirrorTraits) { } public InventoryView openAnvilInventory(Player player, Inventory anvil, String title); diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java index b7e832130..309f1388a 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java @@ -15,7 +15,9 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.TreeMap; +import java.util.UUID; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -54,7 +56,6 @@ import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scoreboard.Team; import org.bukkit.util.Vector; -import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -705,12 +706,7 @@ public class NMSImpl implements NMSBridge { Entity handle = getHandle(entity); if (handle == null || handle.passengers == null) return Lists.newArrayList(); - return Lists.transform(handle.passengers, new Function() { - @Override - public org.bukkit.entity.Entity apply(Entity input) { - return input.getBukkitEntity(); - } - }); + return Lists.transform(handle.passengers, input -> input.getBukkitEntity()); } @Override @@ -777,7 +773,7 @@ public class NMSImpl implements NMSBridge { })); Node last = list.size() > 0 ? list.get(list.size() - 1) : null; final Path path = new Path(list, last != null ? new BlockPos(last.x, last.y, last.z) : null, true); - return getTargetNavigator(entity, params, (input) -> { + return getTargetNavigator(entity, params, input -> { return input.moveTo(path, params.speed()); }); } @@ -1177,7 +1173,7 @@ public class NMSImpl implements NMSBridge { } @Override - public void onPlayerInfoAdd(Player player, Object raw) { + public void onPlayerInfoAdd(Player player, Object raw, Function mirrorTraits) { ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) raw; List list = Lists.newArrayList(packet.entries()); boolean changed = false; @@ -1185,9 +1181,10 @@ public class NMSImpl implements NMSBridge { ClientboundPlayerInfoUpdatePacket.Entry npcInfo = list.get(i); if (npcInfo == null) continue; - NPC npc = CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(npcInfo.profileId()); - if (npc == null || !npc.isSpawned()) + MirrorTrait trait = mirrorTraits.apply(npcInfo.profileId()); + if (trait == null || !trait.isMirroring(player)) { continue; + } if (Setting.DISABLE_TABLIST.asBoolean() != npcInfo.listed()) { list.set(i, new ClientboundPlayerInfoUpdatePacket.Entry(npcInfo.profileId(), npcInfo.profile(), @@ -1196,10 +1193,6 @@ public class NMSImpl implements NMSBridge { npcInfo.chatSession())); changed = true; } - MirrorTrait trait = npc.getTraitNullable(MirrorTrait.class); - if (trait == null || !trait.isMirroring(player)) { - continue; - } GameProfile playerProfile = NMS.getProfile(player); if (trait.mirrorName()) { list.set(i, diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseSkeletonController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseSkeletonController.java index ef6b138d7..bcd51af13 100644 --- a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseSkeletonController.java +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseSkeletonController.java @@ -56,9 +56,9 @@ public class HorseSkeletonController extends MobEntityController { public static class EntityHorseSkeletonNPC extends SkeletonHorse implements NPCHolder { private double baseMovementSpeed; - private final CitizensNPC npc; private boolean riding; + public EntityHorseSkeletonNPC(EntityType types, Level level) { this(types, level, null); } diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java index 8b9e26e8a..30da21b21 100644 --- a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java @@ -18,6 +18,7 @@ import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.Util; import net.minecraft.network.protocol.game.ClientboundAnimatePacket; +import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap.TrackedEntity; import net.minecraft.server.level.ServerEntity; @@ -69,6 +70,8 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity { return; } Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { + NMSImpl.sendPacket(entityplayer.getBukkitEntity(), + new ClientboundRotateHeadPacket(tracker, (byte) (tracker.getYHeadRot() * 256.0F / 360.0F))); NMSImpl.sendPacket(entityplayer.getBukkitEntity(), new ClientboundAnimatePacket(tracker, 0)); NMS.sendTabListRemove(entityplayer.getBukkitEntity(), (Player) tracker.getBukkitEntity()); }, Setting.TABLIST_REMOVE_PACKET_DELAY.asTicks()); diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSImpl.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSImpl.java index 6ca540f25..cbb6af769 100644 --- a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSImpl.java +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSImpl.java @@ -14,7 +14,9 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.TreeMap; +import java.util.UUID; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -53,7 +55,6 @@ import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scoreboard.Team; import org.bukkit.util.Vector; -import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -704,12 +705,7 @@ public class NMSImpl implements NMSBridge { Entity handle = getHandle(entity); if (handle == null || handle.passengers == null) return Lists.newArrayList(); - return Lists.transform(handle.passengers, new Function() { - @Override - public org.bukkit.entity.Entity apply(Entity input) { - return input.getBukkitEntity(); - } - }); + return Lists.transform(handle.passengers, input -> input.getBukkitEntity()); } @Override @@ -1176,7 +1172,7 @@ public class NMSImpl implements NMSBridge { } @Override - public void onPlayerInfoAdd(Player player, Object raw) { + public void onPlayerInfoAdd(Player player, Object raw, Function mirrorTraits) { ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) raw; List list = Lists.newArrayList(packet.entries()); boolean changed = false; @@ -1184,9 +1180,11 @@ public class NMSImpl implements NMSBridge { ClientboundPlayerInfoUpdatePacket.Entry npcInfo = list.get(i); if (npcInfo == null) continue; - NPC npc = CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(npcInfo.profileId()); - if (npc == null || !npc.isSpawned()) + + MirrorTrait trait = mirrorTraits.apply(npcInfo.profileId()); + if (trait == null || !trait.isMirroring(player)) { continue; + } if (Setting.DISABLE_TABLIST.asBoolean() != npcInfo.listed()) { list.set(i, new ClientboundPlayerInfoUpdatePacket.Entry(npcInfo.profileId(), npcInfo.profile(), @@ -1195,10 +1193,6 @@ public class NMSImpl implements NMSBridge { npcInfo.chatSession())); changed = true; } - MirrorTrait trait = npc.getTraitNullable(MirrorTrait.class); - if (trait == null || !trait.isMirroring(player)) { - continue; - } GameProfile playerProfile = NMS.getProfile(player); if (trait.mirrorName()) { list.set(i,