diff --git a/main/src/main/java/net/citizensnpcs/EventListen.java b/main/src/main/java/net/citizensnpcs/EventListen.java index 3bc040e0b..fab571a4f 100644 --- a/main/src/main/java/net/citizensnpcs/EventListen.java +++ b/main/src/main/java/net/citizensnpcs/EventListen.java @@ -4,6 +4,7 @@ import java.lang.reflect.Method; import java.util.List; import java.util.Objects; +import net.citizensnpcs.api.event.NPCMoveEvent; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -214,6 +215,14 @@ public class EventListen implements Listener { if (pbeac != null) { registerPushEvent(pbeac); } + Class paperEntityMoveEventClazz = null; + try { + paperEntityMoveEventClazz = Class.forName("io.papermc.paper.event.entity.EntityMoveEvent"); + } catch (ClassNotFoundException e) { + } + if (paperEntityMoveEventClazz != null) { + registerMoveEvent(paperEntityMoveEventClazz); + } } private void checkCreationEvent(CommandSenderCreateNPCEvent event) { @@ -937,6 +946,44 @@ public class EventListen implements Listener { } } + private void registerMoveEvent(Class clazz) { + try { + final HandlerList handlers = (HandlerList) clazz.getMethod("getHandlerList").invoke(null); + final Method getEntity = clazz.getMethod("getEntity"); + final Method getFrom = clazz.getMethod("getFrom"); + final Method getTo = clazz.getMethod("getTo"); + handlers.register(new RegisteredListener(new Listener() { + }, (listener, event) -> { + if (NPCMoveEvent.getHandlerList().getRegisteredListeners().length == 0 || event.getClass() != clazz) + return; + try { + final Entity entity = (Entity) getEntity.invoke(event); + if (!(entity instanceof NPCHolder)) + return; + final NPC npc = ((NPCHolder) entity).getNPC(); + final Location from = (Location) getFrom.invoke(event); + final Location to = (Location) getTo.invoke(event); + final NPCMoveEvent npcMoveEvent = new NPCMoveEvent(npc, from, to.clone()); + Bukkit.getPluginManager().callEvent(npcMoveEvent); + if (!npcMoveEvent.isCancelled()) { + final Location eventTo = npcMoveEvent.getTo(); + if (!to.equals(eventTo)) { + Bukkit.getScheduler().runTaskLater(plugin, () -> entity.teleport(eventTo), 1L); + } + } else { + final Location eventFrom = npcMoveEvent.getFrom(); + Bukkit.getScheduler().runTaskLater(plugin, () -> entity.teleport(eventFrom), 1L); + } + } catch (Throwable ex) { + ex.printStackTrace(); + } + }, EventPriority.NORMAL, plugin, true)); + } catch (Throwable ex) { + Messaging.severe("Error registering move event forwarder"); + ex.printStackTrace(); + } + } + private void respawnAllFromCoord(ChunkCoord coord, Event event) { List ids = Lists.newArrayList(toRespawn.get(coord)); if (ids.size() > 0) { diff --git a/v1_21_R2/src/main/java/net/citizensnpcs/nms/v1_21_R2/entity/EntityHumanNPC.java b/v1_21_R2/src/main/java/net/citizensnpcs/nms/v1_21_R2/entity/EntityHumanNPC.java index 78a3da4f6..0e6dd7669 100644 --- a/v1_21_R2/src/main/java/net/citizensnpcs/nms/v1_21_R2/entity/EntityHumanNPC.java +++ b/v1_21_R2/src/main/java/net/citizensnpcs/nms/v1_21_R2/entity/EntityHumanNPC.java @@ -149,6 +149,7 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable onGround = false; } pushEntities(); + NMSImpl.callNPCMoveEvent(this); if (npc.useMinecraftAI()) { foodData.tick(this); } diff --git a/v1_21_R2/src/main/java/net/citizensnpcs/nms/v1_21_R2/util/NMSImpl.java b/v1_21_R2/src/main/java/net/citizensnpcs/nms/v1_21_R2/util/NMSImpl.java index 6fe7d3c4a..8c8dde4f8 100644 --- a/v1_21_R2/src/main/java/net/citizensnpcs/nms/v1_21_R2/util/NMSImpl.java +++ b/v1_21_R2/src/main/java/net/citizensnpcs/nms/v1_21_R2/util/NMSImpl.java @@ -18,6 +18,7 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; +import net.citizensnpcs.api.event.NPCMoveEvent; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -2208,6 +2209,24 @@ public class NMSImpl implements NMSBridge { throw new IllegalArgumentException(); } + public static void callNPCMoveEvent(T what) { + final NPC npc = what.getNPC(); + if (npc != null && NPCMoveEvent.getHandlerList().getRegisteredListeners().length > 0) { + if (what.xo != what.getX() || what.yo != what.getY() || what.zo != what.getZ() || what.yRotO != what.getYRot() || what.xRotO != what.getXRot()) { + Location from = new Location(what.level().getWorld(), what.xo, what.yo, what.zo, what.yRotO, what.xRotO); + Location to = new Location(what.level().getWorld(), what.getX(), what.getY(), what.getZ(), what.getYRot(), what.getXRot()); + final NPCMoveEvent event = new NPCMoveEvent(npc, from, to.clone()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + final Location eventFrom = event.getFrom(); + what.absMoveTo(eventFrom.getX(), eventFrom.getY(), eventFrom.getZ(), eventFrom.getYaw(), eventFrom.getPitch()); + } else if (!to.equals(event.getTo())) { + what.absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); + } + } + } + } + public static TreeMap getBehaviorMap(LivingEntity entity) { try { return (TreeMap) AVAILABLE_BEHAVIORS_BY_PRIORITY.invoke(entity.getBrain());