Implement new event

This commit is contained in:
fullwall 2023-11-15 22:39:09 +08:00
parent ad0f5caac5
commit 81cce42a93
35 changed files with 494 additions and 64 deletions

View File

@ -40,7 +40,6 @@ import org.bukkit.plugin.java.JavaPlugin;
* <p> * <p>
* Check out https://bStats.org/ to learn more about bStats! * Check out https://bStats.org/ to learn more about bStats!
*/ */
@SuppressWarnings({ "WeakerAccess", "unused" })
public class Metrics { public class Metrics {

View File

@ -2519,7 +2519,7 @@ public class NPCCommands {
@Command( @Command(
aliases = { "npc" }, aliases = { "npc" },
usage = "rotate (--body [yaw]) (--head [yaw]) (--pitch [pitch]) (-s(mooth))", usage = "rotate (--towards [x,y,z]) (--body [yaw]) (--head [yaw]) (--pitch [pitch]) (-s(mooth))",
desc = "Rotate NPC", desc = "Rotate NPC",
flags = "s", flags = "s",
modifiers = { "rotate" }, modifiers = { "rotate" },
@ -2527,7 +2527,7 @@ public class NPCCommands {
max = 1, max = 1,
permission = "citizens.npc.rotate") permission = "citizens.npc.rotate")
public void rotate(CommandContext args, CommandSender sender, NPC npc, @Flag("body") Float yaw, public void rotate(CommandContext args, CommandSender sender, NPC npc, @Flag("body") Float yaw,
@Flag("head") Float head, @Flag("pitch") Float pitch) { @Flag("head") Float head, @Flag("pitch") Float pitch, @Flag("towards") Location towards) {
if (args.hasFlag('s')) { if (args.hasFlag('s')) {
if (pitch == null) { if (pitch == null) {
pitch = npc.getStoredLocation().getPitch(); pitch = npc.getStoredLocation().getPitch();
@ -2542,6 +2542,10 @@ public class NPCCommands {
npc.getOrAddTrait(RotationTrait.class).getPhysicalSession().rotateToHave(yaw, pitch); npc.getOrAddTrait(RotationTrait.class).getPhysicalSession().rotateToHave(yaw, pitch);
return; return;
} }
if (towards != null) {
npc.getOrAddTrait(RotationTrait.class).getPhysicalSession().rotateToFace(towards);
return;
}
if (yaw != null) { if (yaw != null) {
NMS.setBodyYaw(npc.getEntity(), yaw); NMS.setBodyYaw(npc.getEntity(), yaw);
if (npc.getEntity().getType() == EntityType.PLAYER) { if (npc.getEntity().getType() == EntityType.PLAYER) {

View File

@ -196,8 +196,7 @@ public class CitizensNPC extends AbstractNPC {
@Override @Override
public boolean requiresNameHologram() { public boolean requiresNameHologram() {
return super.requiresNameHologram() return super.requiresNameHologram() || Setting.ALWAYS_USE_NAME_HOLOGRAM.asBoolean();
|| Setting.ALWAYS_USE_NAME_HOLOGRAM.asBoolean() && !data().has(NPC.Metadata.HOLOGRAM_FOR);
} }
private void resetCachedCoord() { private void resetCachedCoord() {

View File

@ -110,10 +110,10 @@ public class HologramTrait extends Trait {
hologramNPC = registry.createNPC(EntityType.ARMOR_STAND, line); hologramNPC = registry.createNPC(EntityType.ARMOR_STAND, line);
hologramNPC.getOrAddTrait(ArmorStandTrait.class).setAsHelperEntityWithName(npc); hologramNPC.getOrAddTrait(ArmorStandTrait.class).setAsHelperEntityWithName(npc);
} }
hologramNPC.data().set(NPC.Metadata.HOLOGRAM_FOR, npc.getUniqueId().toString());
if (Setting.PACKET_HOLOGRAMS.asBoolean()) { if (Setting.PACKET_HOLOGRAMS.asBoolean()) {
hologramNPC.addTrait(PacketNPC.class); hologramNPC.addTrait(PacketNPC.class);
} }
hologramNPC.data().set(NPC.Metadata.HOLOGRAM_FOR, npc.getUniqueId().toString());
if (viewRange != -1) { if (viewRange != -1) {
hologramNPC.data().set(NPC.Metadata.TRACKING_RANGE, viewRange); hologramNPC.data().set(NPC.Metadata.TRACKING_RANGE, viewRange);
} }

View File

@ -28,6 +28,7 @@ public class TextBasePrompt extends StringPrompt {
String input = parts[0]; String input = parts[0];
CommandSender sender = (CommandSender) context.getForWhom(); CommandSender sender = (CommandSender) context.getForWhom();
Messaging.send(sender, getPromptText(context));
if (input.equalsIgnoreCase("add")) { if (input.equalsIgnoreCase("add")) {
text.add(Joiner.on(' ').join(Arrays.copyOfRange(parts, 1, parts.length))); text.add(Joiner.on(' ').join(Arrays.copyOfRange(parts, 1, parts.length)));
return this; return this;
@ -59,10 +60,7 @@ public class TextBasePrompt extends StringPrompt {
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
Messaging.sendErrorTr(sender, Messages.TEXT_EDITOR_INVALID_PAGE); Messaging.sendErrorTr(sender, Messages.TEXT_EDITOR_INVALID_PAGE);
} }
} } else if (input.equalsIgnoreCase("delay")) {
Messaging.send(sender, getPromptText(context));
if (input.equalsIgnoreCase("delay")) {
try { try {
int delay = Integer.parseInt(parts[1]); int delay = Integer.parseInt(parts[1]);
text.setDelay(delay); text.setDelay(delay);

View File

@ -38,7 +38,7 @@ import net.citizensnpcs.util.Util;
@TraitName("bossbar") @TraitName("bossbar")
public class BossBarTrait extends Trait { public class BossBarTrait extends Trait {
private BossBar barCache; private BossBar activeBar;
@Persist @Persist
private BarColor color = BarColor.PURPLE; private BarColor color = BarColor.PURPLE;
@Persist @Persist
@ -65,11 +65,11 @@ public class BossBarTrait extends Trait {
if (npc.isSpawned() && isBoss(npc.getEntity()) && NMS.getBossBar(npc.getEntity()) != null) if (npc.isSpawned() && isBoss(npc.getEntity()) && NMS.getBossBar(npc.getEntity()) != null)
return (BossBar) NMS.getBossBar(npc.getEntity()); return (BossBar) NMS.getBossBar(npc.getEntity());
if (barCache == null) { if (activeBar == null) {
barCache = Bukkit.getServer().createBossBar(npc.getFullName(), color, style, activeBar = Bukkit.getServer().createBossBar(npc.getFullName(), color, style,
flags.toArray(new BarFlag[flags.size()])); flags.toArray(new BarFlag[flags.size()]));
} }
return barCache; return activeBar;
} }
public BarColor getColor() { public BarColor getColor() {
@ -114,12 +114,12 @@ public class BossBarTrait extends Trait {
@Override @Override
public void onDespawn() { public void onDespawn() {
if (barCache == null) if (activeBar == null)
return; return;
barCache.removeAll(); activeBar.removeAll();
barCache.hide(); activeBar.hide();
barCache = null; activeBar = null;
} }
@Override @Override

View File

@ -26,6 +26,10 @@ public class CamelTrait extends Trait {
super("cameltrait"); super("cameltrait");
} }
public CamelPose getPose() {
return pose;
}
@Override @Override
public void run() { public void run() {
if (npc.isSpawned() && npc.getEntity() instanceof Camel) { if (npc.isSpawned() && npc.getEntity() instanceof Camel) {

View File

@ -145,15 +145,15 @@ public class NMS {
BRIDGE.cancelMoveDestination(entity); BRIDGE.cancelMoveDestination(entity);
} }
public static Iterable<Object> createBundlePacket(List<Object> packets) {
return BRIDGE.createBundlePacket(packets);
}
/* /*
* Yggdrasil's default implementation of this method silently fails instead of throwing * Yggdrasil's default implementation of this method silently fails instead of throwing
* an Exception like it should. * an Exception like it should.
*/ */
public static Iterable<Object> createBundlePacket(List<Object> packets) {
return BRIDGE.createBundlePacket(packets);
}
public static EntityPacketTracker createPacketTracker(Entity entity) { public static EntityPacketTracker createPacketTracker(Entity entity) {
return createPacketTracker(entity, new PacketAggregator()); return createPacketTracker(entity, new PacketAggregator());
} }
@ -601,6 +601,10 @@ public class NMS {
return BRIDGE.getVerticalMovement(bukkitEntity); return BRIDGE.getVerticalMovement(bukkitEntity);
} }
public static Collection<Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
return BRIDGE.getViewingPlayers(entity);
}
public static double getWidth(Entity entity) { public static double getWidth(Entity entity) {
return BRIDGE.getWidth(entity); return BRIDGE.getWidth(entity);
} }

View File

@ -116,6 +116,10 @@ public interface NMSBridge {
public float getVerticalMovement(Entity entity); public float getVerticalMovement(Entity entity);
public default Collection<Player> getViewingPlayers(Entity entity) {
return ((Player) entity).getTrackedBy();
}
public double getWidth(Entity entity); public double getWidth(Entity entity);
public float getYaw(Entity entity); public float getYaw(Entity entity);

View File

@ -43,6 +43,7 @@ public class PlayerUpdateTask extends BukkitRunnable {
PLAYERS.put(entity.getUniqueId(), new PlayerTick((Player) entity)); PLAYERS.put(entity.getUniqueId(), new PlayerTick((Player) entity));
} }
} }
// convert to sorted list with binary search
PLAYERS_PENDING_ADD.clear(); PLAYERS_PENDING_ADD.clear();
PLAYERS_PENDING_REMOVE.clear(); PLAYERS_PENDING_REMOVE.clear();

View File

@ -702,6 +702,13 @@ public class NMSImpl implements NMSBridge {
return handle.bf; return handle.bf;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
WorldServer server = (WorldServer) NMSImpl.getHandle(entity).getWorld();
EntityTrackerEntry entry = server.getTracker().trackedEntities.get(entity.getEntityId());
return PlayerlistTrackerEntry.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return getHandle(entity).width; return getHandle(entity).width;

View File

@ -1,6 +1,8 @@
package net.citizensnpcs.nms.v1_10_R1.util; package net.citizensnpcs.nms.v1_10_R1.util;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@ -96,6 +98,10 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
return 0; return 0;
} }
public static Set<org.bukkit.entity.Player> getSeenBy(EntityTrackerEntry tracker) {
return tracker.trackedPlayers.stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
}
private static Entity getTracker(EntityTrackerEntry entry) { private static Entity getTracker(EntityTrackerEntry entry) {
try { try {
return (Entity) TRACKER.get(entry); return (Entity) TRACKER.get(entry);

View File

@ -738,6 +738,13 @@ public class NMSImpl implements NMSBridge {
return handle.be; return handle.be;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
WorldServer server = (WorldServer) NMSImpl.getHandle(entity).getWorld();
EntityTrackerEntry entry = server.getTracker().trackedEntities.get(entity.getEntityId());
return PlayerlistTrackerEntry.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return getHandle(entity).width; return getHandle(entity).width;

View File

@ -4,6 +4,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -12,6 +13,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.NMS;
@ -44,6 +46,16 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
} }
return res; return res;
} }
@Override
public Boolean remove(Object conn) {
Boolean removed = super.remove(conn);
if (removed == true) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -65,6 +77,16 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
protected Set<EntityPlayer> delegate() { protected Set<EntityPlayer> delegate() {
return delegate; return delegate;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -138,6 +160,20 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
return 0; return 0;
} }
public static Set<org.bukkit.entity.Player> getSeenBy(EntityTrackerEntry tracker) {
if (TRACKING_MAP_GETTER != null) {
Map<EntityPlayer, Boolean> delegate;
try {
delegate = (Map<EntityPlayer, Boolean>) TRACKING_MAP_GETTER.invoke(tracker);
} catch (Throwable e) {
return null;
}
return delegate.keySet().stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
} else {
return tracker.trackedPlayers.stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
}
}
private static Entity getTracker(EntityTrackerEntry entry) { private static Entity getTracker(EntityTrackerEntry entry) {
try { try {
return (Entity) TRACKER.get(entry); return (Entity) TRACKER.get(entry);

View File

@ -744,6 +744,13 @@ public class NMSImpl implements NMSBridge {
return handle.be; return handle.be;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
WorldServer server = (WorldServer) NMSImpl.getHandle(entity).getWorld();
EntityTrackerEntry entry = server.getTracker().trackedEntities.get(entity.getEntityId());
return PlayerlistTrackerEntry.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return entity.getWidth(); return entity.getWidth();

View File

@ -4,6 +4,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -12,6 +13,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_12_R1.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_12_R1.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -45,6 +47,16 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
} }
return res; return res;
} }
@Override
public Boolean remove(Object conn) {
Boolean removed = super.remove(conn);
if (removed == true) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -66,6 +78,16 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
protected Set<EntityPlayer> delegate() { protected Set<EntityPlayer> delegate() {
return delegate; return delegate;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -147,6 +169,20 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
return 0; return 0;
} }
public static Set<org.bukkit.entity.Player> getSeenBy(EntityTrackerEntry tracker) {
if (TRACKING_MAP_GETTER != null) {
Map<EntityPlayer, Boolean> delegate;
try {
delegate = (Map<EntityPlayer, Boolean>) TRACKING_MAP_GETTER.invoke(tracker);
} catch (Throwable e) {
return null;
}
return delegate.keySet().stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
} else {
return tracker.trackedPlayers.stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
}
}
private static Entity getTracker(EntityTrackerEntry entry) { private static Entity getTracker(EntityTrackerEntry entry) {
try { try {
return (Entity) TRACKER.get(entry); return (Entity) TRACKER.get(entry);

View File

@ -767,6 +767,13 @@ public class NMSImpl implements NMSBridge {
return handle.bh; return handle.bh;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
WorldServer server = (WorldServer) NMSImpl.getHandle(entity).getWorld();
EntityTrackerEntry entry = server.getTracker().trackedEntities.get(entity.getEntityId());
return PlayerlistTrackerEntry.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return entity.getWidth(); return entity.getWidth();

View File

@ -4,6 +4,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -12,6 +13,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_13_R2.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_13_R2.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -45,6 +47,16 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
} }
return res; return res;
} }
@Override
public Boolean remove(Object conn) {
Boolean removed = super.remove(conn);
if (removed == true) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -66,6 +78,16 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
protected Set<EntityPlayer> delegate() { protected Set<EntityPlayer> delegate() {
return delegate; return delegate;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -146,6 +168,20 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
return 0; return 0;
} }
public static Set<org.bukkit.entity.Player> getSeenBy(EntityTrackerEntry tracker) {
if (TRACKING_MAP_GETTER != null) {
Map<EntityPlayer, Boolean> delegate;
try {
delegate = (Map<EntityPlayer, Boolean>) TRACKING_MAP_GETTER.invoke(tracker);
} catch (Throwable e) {
return null;
}
return delegate.keySet().stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
} else {
return tracker.trackedPlayers.stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
}
}
private static Entity getTracker(EntityTrackerEntry entry) { private static Entity getTracker(EntityTrackerEntry entry) {
try { try {
return (Entity) TRACKER.get(entry); return (Entity) TRACKER.get(entry);

View File

@ -818,6 +818,13 @@ public class NMSImpl implements NMSBridge {
return handle.bb; return handle.bb;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
WorldServer server = (WorldServer) NMSImpl.getHandle(entity).getWorld();
EntityTracker entry = server.getChunkProvider().playerChunkMap.trackedEntities.get(entity.getEntityId());
return PlayerlistTracker.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return entity.getWidth(); return entity.getWidth();

View File

@ -3,6 +3,7 @@ package net.citizensnpcs.nms.v1_14_R1.util;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -11,6 +12,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_14_R1.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_14_R1.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -46,6 +48,16 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
} }
return res; return res;
} }
@Override
public Boolean remove(Object conn) {
Boolean removed = super.remove(conn);
if (removed == true) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -67,6 +79,16 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
protected Set<EntityPlayer> delegate() { protected Set<EntityPlayer> delegate() {
return delegate; return delegate;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -133,6 +155,20 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
return false; return false;
} }
public static Set<org.bukkit.entity.Player> getSeenBy(EntityTracker tracker) {
if (TRACKING_MAP_GETTER != null) {
Map<EntityPlayer, Boolean> delegate;
try {
delegate = (Map<EntityPlayer, Boolean>) TRACKING_MAP_GETTER.invoke(tracker);
} catch (Throwable e) {
return null;
}
return delegate.keySet().stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
} else {
return tracker.trackedPlayers.stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
}
}
private static Entity getTracker(EntityTracker entry) { private static Entity getTracker(EntityTracker entry) {
try { try {
return (Entity) TRACKER.invoke(entry); return (Entity) TRACKER.invoke(entry);

View File

@ -833,6 +833,13 @@ public class NMSImpl implements NMSBridge {
return handle.aZ; return handle.aZ;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
WorldServer server = (WorldServer) NMSImpl.getHandle(entity).getWorld();
EntityTracker entry = server.getChunkProvider().playerChunkMap.trackedEntities.get(entity.getEntityId());
return PlayerlistTracker.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return entity.getWidth(); return entity.getWidth();

View File

@ -3,6 +3,7 @@ package net.citizensnpcs.nms.v1_15_R1.util;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -11,6 +12,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_15_R1.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_15_R1.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -46,6 +48,16 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
} }
return res; return res;
} }
@Override
public Boolean remove(Object conn) {
Boolean removed = super.remove(conn);
if (removed == true) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -67,6 +79,16 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
protected Set<EntityPlayer> delegate() { protected Set<EntityPlayer> delegate() {
return delegate; return delegate;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -133,6 +155,20 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
return false; return false;
} }
public static Set<org.bukkit.entity.Player> getSeenBy(EntityTracker tracker) {
if (TRACKING_MAP_GETTER != null) {
Map<EntityPlayer, Boolean> delegate;
try {
delegate = (Map<EntityPlayer, Boolean>) TRACKING_MAP_GETTER.invoke(tracker);
} catch (Throwable e) {
return null;
}
return delegate.keySet().stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
} else {
return tracker.trackedPlayers.stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
}
}
private static Entity getTracker(EntityTracker entry) { private static Entity getTracker(EntityTracker entry) {
try { try {
return (Entity) TRACKER.invoke(entry); return (Entity) TRACKER.invoke(entry);

View File

@ -857,6 +857,13 @@ public class NMSImpl implements NMSBridge {
return handle.aR; return handle.aR;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
WorldServer server = (WorldServer) NMSImpl.getHandle(entity).getWorld();
EntityTracker entry = server.getChunkProvider().playerChunkMap.trackedEntities.get(entity.getEntityId());
return PlayerlistTracker.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return entity.getWidth(); return entity.getWidth();

View File

@ -3,6 +3,7 @@ package net.citizensnpcs.nms.v1_16_R3.util;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -11,6 +12,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_16_R3.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_16_R3.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -46,6 +48,16 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
} }
return res; return res;
} }
@Override
public Boolean remove(Object conn) {
Boolean removed = super.remove(conn);
if (removed == true) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -67,6 +79,16 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
protected Set<EntityPlayer> delegate() { protected Set<EntityPlayer> delegate() {
return delegate; return delegate;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -133,6 +155,20 @@ public class PlayerlistTracker extends PlayerChunkMap.EntityTracker {
return false; return false;
} }
public static Set<org.bukkit.entity.Player> getSeenBy(EntityTracker tracker) {
if (TRACKING_MAP_GETTER != null) {
Map<EntityPlayer, Boolean> delegate;
try {
delegate = (Map<EntityPlayer, Boolean>) TRACKING_MAP_GETTER.invoke(tracker);
} catch (Throwable e) {
return null;
}
return delegate.keySet().stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
} else {
return tracker.trackedPlayers.stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
}
}
private static Entity getTracker(EntityTracker entry) { private static Entity getTracker(EntityTracker entry) {
try { try {
return (Entity) TRACKER.invoke(entry); return (Entity) TRACKER.invoke(entry);

View File

@ -40,7 +40,6 @@ import net.citizensnpcs.util.Util;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@ -160,14 +159,6 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable
} }
} }
@Override
public Packet<?> getAddEntityPacket() {
if (playerlistTracker != null) {
playerlistTracker.updateLastPlayer();
}
return super.getAddEntityPacket();
}
@Override @Override
public MobAI getAI() { public MobAI getAI() {
return ai; return ai;

View File

@ -860,6 +860,13 @@ public class NMSImpl implements NMSBridge {
return handle.xxa; return handle.xxa;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
ServerLevel server = (ServerLevel) getHandle(entity).level;
TrackedEntity entry = server.getChunkProvider().chunkMap.G.get(entity.getEntityId());
return PlayerlistTracker.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return entity.getWidth(); return entity.getWidth();

View File

@ -1,11 +1,17 @@
package net.citizensnpcs.nms.v1_17_R1.util; package net.citizensnpcs.nms.v1_17_R1.util;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -15,29 +21,52 @@ import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ChunkMap.TrackedEntity; import net.minecraft.server.level.ChunkMap.TrackedEntity;
import net.minecraft.server.level.ServerEntity; import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
public class PlayerlistTracker extends ChunkMap.TrackedEntity { public class PlayerlistTracker extends ChunkMap.TrackedEntity {
private ServerPlayer lastUpdatedPlayer;
private final Entity tracker; private final Entity tracker;
public PlayerlistTracker(ChunkMap map, Entity entity, int i, int j, boolean flag) { public PlayerlistTracker(ChunkMap map, Entity entity, int i, int j, boolean flag) {
map.super(entity, i, j, flag); map.super(entity, i, j, flag);
this.tracker = entity; this.tracker = entity;
try {
Set<ServerPlayerConnection> set = (Set<ServerPlayerConnection>) TRACKING_SET_GETTER.invoke(this);
TRACKING_SET_SETTER.invoke(this, new ForwardingSet<ServerPlayerConnection>() {
@Override
public boolean add(ServerPlayerConnection conn) {
boolean res = super.add(conn);
if (res) {
Bukkit.getPluginManager().callEvent(new NPCLinkToPlayerEvent(((NPCHolder) tracker).getNPC(),
conn.getPlayer().getBukkitEntity()));
}
return res;
}
@Override
protected Set<ServerPlayerConnection> delegate() {
return set;
}
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(((NPCHolder) tracker).getNPC(),
((ServerPlayerConnection) conn).getPlayer().getBukkitEntity()));
}
return removed;
}
});
} catch (Throwable e) {
e.printStackTrace();
}
} }
public PlayerlistTracker(ChunkMap map, TrackedEntity entry) { public PlayerlistTracker(ChunkMap map, TrackedEntity entry) {
this(map, getTracker(entry), getTrackingDistance(entry), getE(entry), getF(entry)); this(map, getTracker(entry), getTrackingDistance(entry), getE(entry), getF(entry));
} }
public void updateLastPlayer() {
if (lastUpdatedPlayer != null) {
Bukkit.getPluginManager().callEvent(
new NPCLinkToPlayerEvent(((NPCHolder) tracker).getNPC(), lastUpdatedPlayer.getBukkitEntity()));
lastUpdatedPlayer = null;
}
}
@Override @Override
public void updatePlayer(final ServerPlayer entityplayer) { public void updatePlayer(final ServerPlayer entityplayer) {
if (entityplayer instanceof EntityHumanNPC) if (entityplayer instanceof EntityHumanNPC)
@ -74,7 +103,6 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
if (cancelled) if (cancelled)
return; return;
} }
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer); super.updatePlayer(entityplayer);
} }
@ -96,6 +124,10 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
return false; return false;
} }
public static Collection<org.bukkit.entity.Player> getSeenBy(TrackedEntity tracker) {
return tracker.seenBy.stream().map(c -> c.getPlayer().getBukkitEntity()).collect(Collectors.toSet());
}
private static Entity getTracker(TrackedEntity entry) { private static Entity getTracker(TrackedEntity entry) {
try { try {
return (Entity) TRACKER.invoke(entry); return (Entity) TRACKER.invoke(entry);
@ -116,9 +148,11 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e");
private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f");
private static volatile Boolean REQUIRES_SYNC; private static volatile Boolean REQUIRES_SYNC = false;
private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class);
private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class);
private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class);
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, int.class); private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, int.class);
private static final MethodHandle TRACKING_SET_GETTER = NMS.getFirstGetter(TrackedEntity.class, Set.class);
private static final MethodHandle TRACKING_SET_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, Set.class);
} }

View File

@ -41,7 +41,6 @@ import net.citizensnpcs.util.Util;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@ -161,14 +160,6 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable
} }
} }
@Override
public Packet<?> getAddEntityPacket() {
if (playerlistTracker != null) {
playerlistTracker.updateLastPlayer();
}
return super.getAddEntityPacket();
}
@Override @Override
public MobAI getAI() { public MobAI getAI() {
return ai; return ai;

View File

@ -867,6 +867,13 @@ public class NMSImpl implements NMSBridge {
return handle.xxa; return handle.xxa;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
ServerLevel server = (ServerLevel) getHandle(entity).level;
TrackedEntity entry = server.getChunkSource().chunkMap.entityMap.get(entity.getEntityId());
return PlayerlistTracker.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return entity.getWidth(); return entity.getWidth();

View File

@ -1,11 +1,17 @@
package net.citizensnpcs.nms.v1_18_R2.util; package net.citizensnpcs.nms.v1_18_R2.util;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_18_R2.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_18_R2.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -15,29 +21,52 @@ import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ChunkMap.TrackedEntity; import net.minecraft.server.level.ChunkMap.TrackedEntity;
import net.minecraft.server.level.ServerEntity; import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
public class PlayerlistTracker extends ChunkMap.TrackedEntity { public class PlayerlistTracker extends ChunkMap.TrackedEntity {
private ServerPlayer lastUpdatedPlayer;
private final Entity tracker; private final Entity tracker;
public PlayerlistTracker(ChunkMap map, Entity entity, int i, int j, boolean flag) { public PlayerlistTracker(ChunkMap map, Entity entity, int i, int j, boolean flag) {
map.super(entity, i, j, flag); map.super(entity, i, j, flag);
this.tracker = entity; this.tracker = entity;
try {
Set<ServerPlayerConnection> set = (Set<ServerPlayerConnection>) TRACKING_SET_GETTER.invoke(this);
TRACKING_SET_SETTER.invoke(this, new ForwardingSet<ServerPlayerConnection>() {
@Override
public boolean add(ServerPlayerConnection conn) {
boolean res = super.add(conn);
if (res) {
Bukkit.getPluginManager().callEvent(new NPCLinkToPlayerEvent(((NPCHolder) tracker).getNPC(),
conn.getPlayer().getBukkitEntity()));
}
return res;
}
@Override
protected Set<ServerPlayerConnection> delegate() {
return set;
}
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(((NPCHolder) tracker).getNPC(),
((ServerPlayerConnection) conn).getPlayer().getBukkitEntity()));
}
return removed;
}
});
} catch (Throwable e) {
e.printStackTrace();
}
} }
public PlayerlistTracker(ChunkMap map, TrackedEntity entry) { public PlayerlistTracker(ChunkMap map, TrackedEntity entry) {
this(map, getTracker(entry), getTrackingDistance(entry), getE(entry), getF(entry)); this(map, getTracker(entry), getTrackingDistance(entry), getE(entry), getF(entry));
} }
public void updateLastPlayer() {
if (lastUpdatedPlayer != null) {
Bukkit.getPluginManager().callEvent(
new NPCLinkToPlayerEvent(((NPCHolder) tracker).getNPC(), lastUpdatedPlayer.getBukkitEntity()));
lastUpdatedPlayer = null;
}
}
@Override @Override
public void updatePlayer(final ServerPlayer entityplayer) { public void updatePlayer(final ServerPlayer entityplayer) {
if (entityplayer instanceof EntityHumanNPC) if (entityplayer instanceof EntityHumanNPC)
@ -74,7 +103,6 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
if (cancelled) if (cancelled)
return; return;
} }
this.lastUpdatedPlayer = entityplayer;
super.updatePlayer(entityplayer); super.updatePlayer(entityplayer);
} }
@ -96,6 +124,10 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
return false; return false;
} }
public static Collection<org.bukkit.entity.Player> getSeenBy(TrackedEntity tracker) {
return tracker.seenBy.stream().map(c -> c.getPlayer().getBukkitEntity()).collect(Collectors.toSet());
}
private static Entity getTracker(TrackedEntity entry) { private static Entity getTracker(TrackedEntity entry) {
try { try {
return (Entity) TRACKER.invoke(entry); return (Entity) TRACKER.invoke(entry);
@ -116,9 +148,11 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity {
private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e");
private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f");
private static volatile Boolean REQUIRES_SYNC; private static volatile Boolean REQUIRES_SYNC = false;
private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class);
private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class);
private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class);
private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, int.class); private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, int.class);
private static final MethodHandle TRACKING_SET_GETTER = NMS.getFirstGetter(TrackedEntity.class, Set.class);
private static final MethodHandle TRACKING_SET_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, Set.class);
} }

View File

@ -1,7 +1,9 @@
package net.citizensnpcs.nms.v1_19_R3.util; package net.citizensnpcs.nms.v1_19_R3.util;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Collection;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -9,6 +11,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_19_R3.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_19_R3.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -44,6 +47,16 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity {
protected Set<ServerPlayerConnection> delegate() { protected Set<ServerPlayerConnection> delegate() {
return set; return set;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(((NPCHolder) tracker).getNPC(),
((ServerPlayerConnection) conn).getPlayer().getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -111,6 +124,10 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity {
return false; return false;
} }
public static Collection<org.bukkit.entity.Player> getSeenBy(TrackedEntity tracker) {
return tracker.seenBy.stream().map(c -> c.getPlayer().getBukkitEntity()).collect(Collectors.toSet());
}
private static Entity getTracker(TrackedEntity entry) { private static Entity getTracker(TrackedEntity entry) {
try { try {
return (Entity) TRACKER.invoke(entry); return (Entity) TRACKER.invoke(entry);

View File

@ -907,6 +907,13 @@ public class NMSImpl implements NMSBridge {
return handle.xxa; return handle.xxa;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
ServerLevel server = (ServerLevel) getHandle(entity).level;
TrackedEntity entry = server.getChunkSource().chunkMap.entityMap.get(entity.getEntityId());
return CitizensEntityTracker.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return entity.getWidth(); return entity.getWidth();

View File

@ -1,7 +1,9 @@
package net.citizensnpcs.nms.v1_20_R2.util; package net.citizensnpcs.nms.v1_20_R2.util;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Collection;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -9,6 +11,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_20_R2.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_20_R2.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -44,6 +47,16 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity {
protected Set<ServerPlayerConnection> delegate() { protected Set<ServerPlayerConnection> delegate() {
return set; return set;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(((NPCHolder) tracker).getNPC(),
((ServerPlayerConnection) conn).getPlayer().getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -94,6 +107,10 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity {
super.updatePlayer(entityplayer); super.updatePlayer(entityplayer);
} }
public static Collection<org.bukkit.entity.Entity> getSeenBy(TrackedEntity tracker) {
return tracker.seenBy.stream().map(c -> c.getPlayer().getBukkitEntity()).collect(Collectors.toSet());
}
private static boolean getTrackDelta(TrackedEntity entry) { private static boolean getTrackDelta(TrackedEntity entry) {
try { try {
return (boolean) TRACK_DELTA.invoke(TRACKER_ENTRY.invoke(entry)); return (boolean) TRACK_DELTA.invoke(TRACKER_ENTRY.invoke(entry));

View File

@ -646,6 +646,13 @@ public class NMSImpl implements NMSBridge {
return handle.aZ; return handle.aZ;
} }
@Override
public Collection<org.bukkit.entity.Player> getViewingPlayers(org.bukkit.entity.Entity entity) {
WorldServer server = (WorldServer) NMSImpl.getHandle(entity).getWorld();
EntityTrackerEntry entry = server.getTracker().trackedEntities.get(entity.getEntityId());
return PlayerlistTrackerEntry.getSeenBy(entry);
}
@Override @Override
public double getWidth(org.bukkit.entity.Entity entity) { public double getWidth(org.bukkit.entity.Entity entity) {
return getHandle(entity).width; return getHandle(entity).width;
@ -1787,9 +1794,7 @@ public class NMSImpl implements NMSBridge {
private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.SILVERFISH, EntityType.ENDERMITE, private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.SILVERFISH, EntityType.ENDERMITE,
EntityType.ENDER_DRAGON, EntityType.BAT, EntityType.SLIME, EntityType.MAGMA_CUBE, EntityType.HORSE, EntityType.ENDER_DRAGON, EntityType.BAT, EntityType.SLIME, EntityType.MAGMA_CUBE, EntityType.HORSE,
EntityType.GHAST); EntityType.GHAST);
private static final float DEFAULT_SPEED = 1F; private static final float DEFAULT_SPEED = 1F;
public static MethodHandle ENDERDRAGON_CHECK_WALLS = NMS.getFirstMethodHandleWithReturnType(EntityEnderDragon.class, public static MethodHandle ENDERDRAGON_CHECK_WALLS = NMS.getFirstMethodHandleWithReturnType(EntityEnderDragon.class,
true, boolean.class, AxisAlignedBB.class); true, boolean.class, AxisAlignedBB.class);
private static Method ENTITY_ATTACK_A = NMS.getMethod(Entity.class, "a", true, EntityLiving.class, Entity.class); private static Method ENTITY_ATTACK_A = NMS.getMethod(Entity.class, "a", true, EntityLiving.class, Entity.class);

View File

@ -4,6 +4,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -12,6 +13,7 @@ import com.google.common.collect.ForwardingSet;
import net.citizensnpcs.api.event.NPCLinkToPlayerEvent; import net.citizensnpcs.api.event.NPCLinkToPlayerEvent;
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
import net.citizensnpcs.api.event.NPCUnlinkFromPlayerEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.nms.v1_8_R3.entity.EntityHumanNPC; import net.citizensnpcs.nms.v1_8_R3.entity.EntityHumanNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
@ -43,6 +45,16 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
} }
return res; return res;
} }
@Override
public Boolean remove(Object conn) {
Boolean removed = super.remove(conn);
if (removed == true) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -64,6 +76,16 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
protected Set<EntityPlayer> delegate() { protected Set<EntityPlayer> delegate() {
return delegate; return delegate;
} }
@Override
public boolean remove(Object conn) {
boolean removed = super.remove(conn);
if (removed) {
Bukkit.getPluginManager().callEvent(new NPCUnlinkFromPlayerEvent(
((NPCHolder) tracker).getNPC(), ((EntityPlayer) conn).getBukkitEntity()));
}
return removed;
}
}); });
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -126,6 +148,20 @@ public class PlayerlistTrackerEntry extends EntityTrackerEntry {
return 0; return 0;
} }
public static Set<org.bukkit.entity.Player> getSeenBy(EntityTrackerEntry tracker) {
if (TRACKING_MAP_GETTER != null) {
Map<EntityPlayer, Boolean> delegate;
try {
delegate = (Map<EntityPlayer, Boolean>) TRACKING_MAP_GETTER.invoke(tracker);
} catch (Throwable e) {
return null;
}
return delegate.keySet().stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
} else {
return tracker.trackedPlayers.stream().map(p -> p.getBukkitEntity()).collect(Collectors.toSet());
}
}
private static boolean getU(EntityTrackerEntry entry) { private static boolean getU(EntityTrackerEntry entry) {
try { try {
return (Boolean) U.get(entry); return (Boolean) U.get(entry);