diff --git a/src/main/java/net/citizensnpcs/api/LocationLookup.java b/src/main/java/net/citizensnpcs/api/LocationLookup.java index 426615ba..748e275b 100644 --- a/src/main/java/net/citizensnpcs/api/LocationLookup.java +++ b/src/main/java/net/citizensnpcs/api/LocationLookup.java @@ -11,15 +11,19 @@ import java.util.function.BiConsumer; import org.bukkit.Bukkit; +import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.world.WorldUnloadEvent; +import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import com.google.common.collect.Collections2; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -66,6 +70,32 @@ public Iterable getNearbyPlayers(NPC npc) { return getNearbyPlayers(npc.getStoredLocation(), npc.data().get(NPC.Metadata.TRACKING_RANGE, 64)); } + public Iterable getNearbyVisiblePlayers(Entity entity, double range) { + return getNearbyVisiblePlayers(entity, entity.getLocation(), range); + } + + public Iterable getNearbyVisiblePlayers(Entity base, Location location, double dist) { + Player player = base instanceof Player ? (Player) base : null; + return Iterables.filter(getNearbyPlayers(location, dist), other -> { + boolean canSee = true; + if (SUPPORTS_ENTITY_CANSEE) { + try { + canSee = other.canSee(base); + } catch (NoSuchMethodError t) { + SUPPORTS_ENTITY_CANSEE = false; + if (player != null) { + canSee = other.canSee(player); + } + } + } else if (player != null) { + canSee = other.canSee(player); + } + return other.getWorld() == base.getWorld() && canSee + && !other.hasPotionEffect(PotionEffectType.INVISIBILITY) + && other.getGameMode() != GameMode.SPECTATOR; + }); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) public void onJoin(PlayerJoinEvent event) { Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { @@ -226,4 +256,6 @@ public Node(double[] loc, T t) { } } } + + private static boolean SUPPORTS_ENTITY_CANSEE = true; } diff --git a/src/main/java/net/citizensnpcs/api/npc/SimpleNPCDataStore.java b/src/main/java/net/citizensnpcs/api/npc/SimpleNPCDataStore.java index 6243bc82..ae059957 100644 --- a/src/main/java/net/citizensnpcs/api/npc/SimpleNPCDataStore.java +++ b/src/main/java/net/citizensnpcs/api/npc/SimpleNPCDataStore.java @@ -54,8 +54,8 @@ public void loadInto(NPCRegistry registry) { continue; } NPC npc = registry.createNPC(type, - !key.getString("uuid", "").isEmpty() ? UUID.fromString(key.getString("uuid")) : UUID.randomUUID(), - id, key.getString("name")); + !key.getString("uuid").isEmpty() ? UUID.fromString(key.getString("uuid")) : UUID.randomUUID(), id, + key.getString("name")); npc.load(key); } } diff --git a/src/main/java/net/citizensnpcs/api/util/ItemStorage.java b/src/main/java/net/citizensnpcs/api/util/ItemStorage.java index e0f1ef42..7127b4a3 100644 --- a/src/main/java/net/citizensnpcs/api/util/ItemStorage.java +++ b/src/main/java/net/citizensnpcs/api/util/ItemStorage.java @@ -210,7 +210,7 @@ private static void deserialiseMeta(DataKey root, ItemStack res) { OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(UUID.fromString(root.getString("skull.uuid"))); meta.setOwningPlayer(offlinePlayer); } else if (root.keyExists("skull.owner") && !root.getString("skull.owner").isEmpty()) { - meta.setOwner(root.getString("skull.owner", "")); + meta.setOwner(root.getString("skull.owner")); } if (root.keyExists("skull.texture") && !root.getString("skull.texture").isEmpty()) { CitizensAPI.getNMSHelper().setTexture(root.getString("skull.texture", ""), meta); diff --git a/src/main/java/net/citizensnpcs/api/util/Placeholders.java b/src/main/java/net/citizensnpcs/api/util/Placeholders.java index 754c3013..ba75a630 100644 --- a/src/main/java/net/citizensnpcs/api/util/Placeholders.java +++ b/src/main/java/net/citizensnpcs/api/util/Placeholders.java @@ -90,13 +90,13 @@ private static String getWorldReplacement(Location location, String group, Entit double min = Double.MAX_VALUE; Entity closest = null; for (Player entity : CitizensAPI.getLocationLookup().getNearbyPlayers(location, 25)) { - if (entity == excluding || CitizensAPI.getNPCRegistry().isNPC(entity)) { + if (entity == excluding || CitizensAPI.getNPCRegistry().isNPC(entity)) continue; - } + double dist = entity.getLocation().distanceSquared(location); - if (dist > min) { + if (dist > min) continue; - } + min = dist; closest = entity; } @@ -136,6 +136,9 @@ private static String replace(String text, CommandSender sender, NPC npc, boolea String replacement = ""; String group = matcher.group(1); switch (group) { + case "uuid": + replacement = npc.getUniqueId().toString(); + break; case "id": replacement = Integer.toString(npc.getId()); break; @@ -171,27 +174,25 @@ public static String replace(String text, OfflinePlayer player) { return setPlaceholderAPIPlaceholders(text, player); if (text == null) return text; - if (player.getPlayer() != null) { - StringBuffer out = new StringBuffer(); - Matcher matcher = PLAYER_PLACEHOLDER_MATCHER.matcher(text); - while (matcher.find()) { - String replacement = ""; - String group = matcher.group(1); - if (PLAYER_VARIABLES.contains(group)) { - replacement = player.getName(); - } else { - replacement = getWorldReplacement(player.getPlayer().getLocation(), group, player.getPlayer()); - } - matcher.appendReplacement(out, ""); - out.append(replacement); - } - matcher.appendTail(out); - text = out.toString(); - } else { - for (int i = 0; i < PLAYER_PLACEHOLDERS.length; i++) { - text = text.replace(PLAYER_PLACEHOLDERS[i], player.getName()); + StringBuffer out = new StringBuffer(); + Matcher matcher = PLAYER_PLACEHOLDER_MATCHER.matcher(text); + while (matcher.find()) { + String replacement = ""; + String group = matcher.group(1); + if (PLAYER_VARIABLES.contains(group)) { + replacement = player.getName(); + } else if (PLAYER_UUID_VARIABLES.contains(group)) { + replacement = player.getUniqueId().toString(); + } else if (player.getPlayer() != null) { + replacement = getWorldReplacement(player.getPlayer().getLocation(), group, player.getPlayer()); + } else { + replacement = group; } + matcher.appendReplacement(out, ""); + out.append(replacement); } + matcher.appendTail(out); + text = out.toString(); return setPlaceholderAPIPlaceholders(text, player); } @@ -215,7 +216,7 @@ private static String setPlaceholderAPIPlaceholders(String text, OfflinePlayer p private static boolean PLACEHOLDERAPI_ENABLED = true; private static final List PLACEHOLDERS = Lists.newArrayList(); private static final Pattern PLAYER_PLACEHOLDER_MATCHER = Pattern.compile( - "(|

|%player%|||||||)"); - private static final String[] PLAYER_PLACEHOLDERS = { "", "

", "%player%" }; + "(|

|%player%||||||||)"); + private static final Collection PLAYER_UUID_VARIABLES = ImmutableSet.of(""); private static final Collection PLAYER_VARIABLES = ImmutableSet.of("", "

", "%player%"); }