From ed89011dbc4fbf7f84315c1d303a69ff44a6a62c Mon Sep 17 00:00:00 2001 From: Julian <42209193+juliarn@users.noreply.github.com> Date: Mon, 18 May 2020 21:57:40 +0200 Subject: [PATCH 1/7] Add NPC respawn on Player respawn --- src/main/java/com/github/juliarn/npc/NPCPool.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/github/juliarn/npc/NPCPool.java b/src/main/java/com/github/juliarn/npc/NPCPool.java index 3ecffc7..eb03f56 100644 --- a/src/main/java/com/github/juliarn/npc/NPCPool.java +++ b/src/main/java/com/github/juliarn/npc/NPCPool.java @@ -19,6 +19,7 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -139,6 +140,18 @@ public void removeNPC(int entityId) { } } + @EventHandler + public void handleRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + + this.npcMap.values().stream() + .filter(npc -> npc.isShownFor(player)) + .forEach(npc -> { + npc.hide(player); + npc.show(player, this.javaPlugin, this.tabListRemoveTicks); + }); + } + @EventHandler public void handleQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); From 6e36f73e9c43e75f6845d816c276b04720cc8c52 Mon Sep 17 00:00:00 2001 From: Julian <42209193+juliarn@users.noreply.github.com> Date: Mon, 18 May 2020 22:52:08 +0200 Subject: [PATCH 2/7] Add world checks to imitate events :life: --- src/main/java/com/github/juliarn/npc/NPCPool.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/juliarn/npc/NPCPool.java b/src/main/java/com/github/juliarn/npc/NPCPool.java index eb03f56..2f3102c 100644 --- a/src/main/java/com/github/juliarn/npc/NPCPool.java +++ b/src/main/java/com/github/juliarn/npc/NPCPool.java @@ -166,7 +166,8 @@ public void handleSneak(PlayerToggleSneakEvent event) { Player player = event.getPlayer(); this.npcMap.values().stream() - .filter(npc -> npc.isImitatePlayer() && npc.isShownFor(player) && npc.getLocation().distanceSquared(player.getLocation()) <= this.actionDistance) + .filter(npc -> npc.isImitatePlayer() && npc.isShownFor(player)) + .filter(npc -> npc.getLocation().getWorld().equals(player.getWorld()) && npc.getLocation().distanceSquared(player.getLocation()) <= this.actionDistance) .forEach(npc -> npc.metadata().queue(MetadataModifier.EntityMetadata.SNEAKING, event.isSneaking()).send(player)); } @@ -176,7 +177,8 @@ public void handleClick(PlayerInteractEvent event) { if (event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) { this.npcMap.values().stream() - .filter(npc -> npc.isImitatePlayer() && npc.isShownFor(player) && npc.getLocation().distanceSquared(player.getLocation()) <= this.actionDistance) + .filter(npc -> npc.isImitatePlayer() && npc.isShownFor(player)) + .filter(npc -> npc.getLocation().getWorld().equals(player.getWorld()) && npc.getLocation().distanceSquared(player.getLocation()) <= this.actionDistance) .forEach(npc -> npc.animation().queue(AnimationModifier.EntityAnimation.SWING_MAIN_ARM).send(player)); } } From fbe9b64801af934b45d3728f326959982b761c30 Mon Sep 17 00:00:00 2001 From: Julian <42209193+juliarn@users.noreply.github.com> Date: Tue, 13 Oct 2020 15:04:22 +0200 Subject: [PATCH 3/7] Fix entity equipment packet for 1.16 --- pom.xml | 4 ++-- .../npc/modifier/EquipmentModifier.java | 24 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 74a98d4..26fdbfe 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.juliarn npc-lib - 2.3-RELEASE + 2.4-RELEASE jar @@ -46,7 +46,7 @@ com.comphenix.protocol ProtocolLib - 4.5.0 + 4.6.0-SNAPSHOT provided diff --git a/src/main/java/com/github/juliarn/npc/modifier/EquipmentModifier.java b/src/main/java/com/github/juliarn/npc/modifier/EquipmentModifier.java index b28fb8d..36f9c5c 100644 --- a/src/main/java/com/github/juliarn/npc/modifier/EquipmentModifier.java +++ b/src/main/java/com/github/juliarn/npc/modifier/EquipmentModifier.java @@ -4,10 +4,13 @@ import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.wrappers.EnumWrappers; +import com.comphenix.protocol.wrappers.Pair; import com.github.juliarn.npc.NPC; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import java.util.Collections; + public class EquipmentModifier extends NPCModifier { public EquipmentModifier(@NotNull NPC npc) { @@ -17,8 +20,12 @@ public EquipmentModifier(@NotNull NPC npc) { public EquipmentModifier queue(@NotNull EnumWrappers.ItemSlot itemSlot, @NotNull ItemStack equipment) { PacketContainer packetContainer = super.newContainer(PacketType.Play.Server.ENTITY_EQUIPMENT); - packetContainer.getItemSlots().write(MINECRAFT_VERSION < 9 ? 1 : 0, itemSlot); - packetContainer.getItemModifier().write(0, equipment); + if (MINECRAFT_VERSION < 16) { + packetContainer.getItemSlots().write(MINECRAFT_VERSION < 9 ? 1 : 0, itemSlot); + packetContainer.getItemModifier().write(0, equipment); + } else { + packetContainer.getSlotStackPairLists().write(0, Collections.singletonList(new Pair<>(itemSlot, equipment))); + } return this; } @@ -26,8 +33,17 @@ public EquipmentModifier queue(@NotNull EnumWrappers.ItemSlot itemSlot, @NotNull public EquipmentModifier queue(int itemSlot, @NotNull ItemStack equipment) { PacketContainer packetContainer = super.newContainer(PacketType.Play.Server.ENTITY_EQUIPMENT); - packetContainer.getIntegers().write(MINECRAFT_VERSION < 9 ? 1 : 0, itemSlot); - packetContainer.getItemModifier().write(0, equipment); + if (MINECRAFT_VERSION < 16) { + packetContainer.getIntegers().write(MINECRAFT_VERSION < 9 ? 1 : 0, itemSlot); + packetContainer.getItemModifier().write(0, equipment); + } else { + for (EnumWrappers.ItemSlot slot : EnumWrappers.ItemSlot.values()) { + if (slot.ordinal() == itemSlot) { + packetContainer.getSlotStackPairLists().write(0, Collections.singletonList(new Pair<>(slot, equipment))); + break; + } + } + } return this; } From dac967db3e57d982439b06639aef98376ad6e77c Mon Sep 17 00:00:00 2001 From: Julian <42209193+juliarn@users.noreply.github.com> Date: Tue, 13 Oct 2020 15:25:06 +0200 Subject: [PATCH 4/7] Add possibility to exclude players from seeing the NPC. fixes #21 --- src/main/java/com/github/juliarn/npc/NPC.java | 31 +++++++++++++++++++ .../java/com/github/juliarn/npc/NPCPool.java | 13 +++++--- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/juliarn/npc/NPC.java b/src/main/java/com/github/juliarn/npc/NPC.java index dd13844..ec3f110 100644 --- a/src/main/java/com/github/juliarn/npc/NPC.java +++ b/src/main/java/com/github/juliarn/npc/NPC.java @@ -21,6 +21,8 @@ public class NPC { private final Collection seeingPlayers = new CopyOnWriteArraySet<>(); + private final Collection excludedPlayers = new CopyOnWriteArraySet<>(); + private final int entityId = RANDOM.nextInt(Short.MAX_VALUE); private final WrappedGameProfile gameProfile; @@ -81,6 +83,35 @@ public boolean isShownFor(Player player) { return this.seeingPlayers.contains(player); } + /** + * Adds a player which should be explicitly excluded from seeing this NPC + * + * @param player the player to be excluded + */ + public void addExcludedPlayer(Player player) { + this.excludedPlayers.add(player); + } + + /** + * Removes a player from being explicitly excluded from seeing this NPC + * + * @param player the player to be included again + */ + public void removeExcludedPlayer(Player player) { + this.excludedPlayers.remove(player); + } + + /** + * @return a modifiable collection of all players which are explicitly excluded from seeing this NPC + */ + public Collection getExcludedPlayers() { + return this.excludedPlayers; + } + + public boolean isExcluded(Player player) { + return this.excludedPlayers.contains(player); + } + /** * Creates a new animation modifier which serves methods to play animations on an NPC * diff --git a/src/main/java/com/github/juliarn/npc/NPCPool.java b/src/main/java/com/github/juliarn/npc/NPCPool.java index 2f3102c..0723bac 100644 --- a/src/main/java/com/github/juliarn/npc/NPCPool.java +++ b/src/main/java/com/github/juliarn/npc/NPCPool.java @@ -108,13 +108,13 @@ private void npcTick() { double distance = npc.getLocation().distanceSquared(player.getLocation()); - if (distance >= this.spawnDistance && npc.isShownFor(player)) { + if ((npc.isExcluded(player) || distance >= this.spawnDistance) && npc.isShownFor(player)) { npc.hide(player); - } else if (distance <= this.spawnDistance && !npc.isShownFor(player)) { + } else if ((!npc.isExcluded(player) && distance <= this.spawnDistance) && !npc.isShownFor(player)) { npc.show(player, this.javaPlugin, this.tabListRemoveTicks); } - if (npc.isLookAtPlayer() && distance <= this.actionDistance) { + if (npc.isShownFor(player) && npc.isLookAtPlayer() && distance <= this.actionDistance) { npc.rotation().queueLookAt(player.getLocation()).send(player); } } @@ -157,8 +157,11 @@ public void handleQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); this.npcMap.values().stream() - .filter(npc -> npc.isShownFor(player)) - .forEach(npc -> npc.removeSeeingPlayer(player)); + .filter(npc -> npc.isShownFor(player) || npc.isExcluded(player)) + .forEach(npc -> { + npc.removeSeeingPlayer(player); + npc.removeExcludedPlayer(player); + }); } @EventHandler From 7116207773d705b88762ca6f0038ec2d097d4044 Mon Sep 17 00:00:00 2001 From: Julian <42209193+juliarn@users.noreply.github.com> Date: Tue, 13 Oct 2020 15:26:22 +0200 Subject: [PATCH 5/7] Update README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6c8ee7c..f8b38cb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # NPC-Lib -Minecraft NPC library for 1.8-1.15 servers. +Minecraft NPC library for 1.8-1.16 servers. This Library does only support the latest patch release of a supported version (for example 1.13.2). Issues with older patch versions (for example 1.13.1) won't be fixed. @@ -20,7 +20,7 @@ Maven com.github.juliarn npc-lib - 2.3-RELEASE + 2.4-RELEASE ``` @@ -31,7 +31,7 @@ maven { url 'https://jitpack.io' } -compile group: 'com.github.juliarn', name: 'npc-lib', version: '2.3-RELEASE' +compile group: 'com.github.juliarn', name: 'npc-lib', version: '2.4-RELEASE' ``` Add ProtocolLib as dependency to your plugin.yml. It could look like this: From d48524cb7ada1895b0d9a852d9159a2bd2e6f3b5 Mon Sep 17 00:00:00 2001 From: Julian <42209193+juliarn@users.noreply.github.com> Date: Tue, 13 Oct 2020 16:27:33 +0200 Subject: [PATCH 6/7] Fix invisible NPCs after death or world switch --- src/main/java/com/github/juliarn/npc/NPCPool.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/juliarn/npc/NPCPool.java b/src/main/java/com/github/juliarn/npc/NPCPool.java index 0723bac..5449a07 100644 --- a/src/main/java/com/github/juliarn/npc/NPCPool.java +++ b/src/main/java/com/github/juliarn/npc/NPCPool.java @@ -103,6 +103,9 @@ private void npcTick() { for (Player player : ImmutableList.copyOf(Bukkit.getOnlinePlayers())) { for (NPC npc : this.npcMap.values()) { if (!npc.getLocation().getWorld().equals(player.getLocation().getWorld())) { + if (npc.isShownFor(player)) { + npc.hide(player); + } continue; } @@ -146,10 +149,7 @@ public void handleRespawn(PlayerRespawnEvent event) { this.npcMap.values().stream() .filter(npc -> npc.isShownFor(player)) - .forEach(npc -> { - npc.hide(player); - npc.show(player, this.javaPlugin, this.tabListRemoveTicks); - }); + .forEach(npc -> npc.hide(player)); } @EventHandler From 2095627dba97d7011a218ac2714fc23fb6f1a722 Mon Sep 17 00:00:00 2001 From: Julian <42209193+juliarn@users.noreply.github.com> Date: Tue, 13 Oct 2020 17:09:14 +0200 Subject: [PATCH 7/7] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f8b38cb..4733814 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # NPC-Lib -Minecraft NPC library for 1.8-1.16 servers. +Asynchronous, high-performance Minecraft NPC library for 1.8-1.16 servers. + This Library does only support the latest patch release of a supported version (for example 1.13.2). Issues with older patch versions (for example 1.13.1) won't be fixed.