mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2025-01-23 00:21:31 +01:00
Merge branch 'master' of github.com:CitizensDev/Citizens2
This commit is contained in:
commit
b26540619b
@ -1,234 +1,236 @@
|
||||
package net.citizensnpcs.trait;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.command.CommandConfigurable;
|
||||
import net.citizensnpcs.api.command.CommandContext;
|
||||
import net.citizensnpcs.api.persistence.Persist;
|
||||
import net.citizensnpcs.api.trait.Trait;
|
||||
import net.citizensnpcs.api.trait.TraitName;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.util.NMS;
|
||||
import net.citizensnpcs.util.Util;
|
||||
|
||||
/**
|
||||
* Persists the /npc lookclose metadata
|
||||
*
|
||||
*/
|
||||
@TraitName("lookclose")
|
||||
public class LookClose extends Trait implements Toggleable, CommandConfigurable {
|
||||
@Persist("enabled")
|
||||
private boolean enabled = Setting.DEFAULT_LOOK_CLOSE.asBoolean();
|
||||
@Persist
|
||||
private boolean enableRandomLook = Setting.DEFAULT_RANDOM_LOOK_CLOSE.asBoolean();
|
||||
private Player lookingAt;
|
||||
@Persist
|
||||
private int randomLookDelay = Setting.DEFAULT_RANDOM_LOOK_DELAY.asInt();
|
||||
@Persist
|
||||
private float[] randomPitchRange = { -10, 0 };
|
||||
@Persist
|
||||
private float[] randomYawRange = { 0, 360 };
|
||||
private double range = Setting.DEFAULT_LOOK_CLOSE_RANGE.asDouble();
|
||||
@Persist("realisticlooking")
|
||||
private boolean realisticLooking = Setting.DEFAULT_REALISTIC_LOOKING.asBoolean();
|
||||
private int t;
|
||||
|
||||
public LookClose() {
|
||||
super("lookclose");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the target can be seen. Will use realistic line of sight if
|
||||
* {@link #setRealisticLooking(boolean)} is true.
|
||||
*/
|
||||
public boolean canSeeTarget() {
|
||||
return realisticLooking && npc.getEntity() instanceof LivingEntity
|
||||
? ((LivingEntity) npc.getEntity()).hasLineOfSight(lookingAt)
|
||||
: lookingAt != null && lookingAt.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(CommandContext args) {
|
||||
range = args.getFlagDouble("range", args.getFlagDouble("r", range));
|
||||
realisticLooking = args.hasFlag('r');
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a new look-close target
|
||||
*/
|
||||
public void findNewTarget() {
|
||||
List<Entity> nearby = npc.getEntity().getNearbyEntities(range, range, range);
|
||||
Collections.sort(nearby, new Comparator<Entity>() {
|
||||
@Override
|
||||
public int compare(Entity o1, Entity o2) {
|
||||
Location l1 = o1.getLocation(CACHE_LOCATION);
|
||||
Location l2 = o2.getLocation(CACHE_LOCATION2);
|
||||
if (!NPC_LOCATION.getWorld().equals(l1.getWorld()) || !NPC_LOCATION.getWorld().equals(l2.getWorld())) {
|
||||
return -1;
|
||||
}
|
||||
return Double.compare(l1.distanceSquared(NPC_LOCATION), l2.distanceSquared(NPC_LOCATION));
|
||||
}
|
||||
});
|
||||
for (Entity entity : nearby) {
|
||||
if (entity.getType() != EntityType.PLAYER || ((Player) entity).getGameMode() == GameMode.SPECTATOR
|
||||
|| ((Player) entity).hasPotionEffect(PotionEffectType.INVISIBILITY)
|
||||
|| isPluginVanished((Player) entity)
|
||||
|| entity.getLocation(CACHE_LOCATION).getWorld() != NPC_LOCATION.getWorld()
|
||||
|| CitizensAPI.getNPCRegistry().getNPC(entity) != null)
|
||||
continue;
|
||||
lookingAt = (Player) entity;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasInvalidTarget() {
|
||||
if (lookingAt == null)
|
||||
return true;
|
||||
if (!lookingAt.isOnline() || lookingAt.getWorld() != npc.getEntity().getWorld()
|
||||
|| lookingAt.getLocation(PLAYER_LOCATION).distanceSquared(NPC_LOCATION) > range) {
|
||||
lookingAt = null;
|
||||
}
|
||||
return lookingAt == null;
|
||||
}
|
||||
|
||||
private boolean isPluginVanished(Player player) {
|
||||
for (MetadataValue meta : player.getMetadata("vanished")) {
|
||||
if (meta.asBoolean()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(DataKey key) {
|
||||
range = key.getDouble("range");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables the trait
|
||||
*/
|
||||
public void lookClose(boolean lookClose) {
|
||||
enabled = lookClose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDespawn() {
|
||||
lookingAt = null;
|
||||
}
|
||||
|
||||
private void randomLook() {
|
||||
Random rand = new Random();
|
||||
float pitch = rand.doubles(randomPitchRange[0], randomPitchRange[1]).iterator().next().floatValue(),
|
||||
yaw = rand.doubles(randomYawRange[0], randomYawRange[1]).iterator().next().floatValue();
|
||||
Util.assumePose(npc.getEntity(), yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!enabled || !npc.isSpawned()) {
|
||||
return;
|
||||
}
|
||||
if (npc.getNavigator().isNavigating() && Setting.DISABLE_LOOKCLOSE_WHILE_NAVIGATING.asBoolean()) {
|
||||
return;
|
||||
}
|
||||
// TODO: remove in a later version, defaults weren't saving properly
|
||||
if (randomPitchRange == null || randomPitchRange.length != 2) {
|
||||
randomPitchRange = new float[] { -10, 0 };
|
||||
}
|
||||
if (randomYawRange == null || randomYawRange.length != 2) {
|
||||
randomYawRange = new float[] { 0, 360 };
|
||||
}
|
||||
npc.getEntity().getLocation(NPC_LOCATION);
|
||||
if (hasInvalidTarget()) {
|
||||
findNewTarget();
|
||||
}
|
||||
if (npc.getNavigator().isNavigating()) {
|
||||
npc.getNavigator().setPaused(lookingAt != null);
|
||||
} else if (lookingAt == null && enableRandomLook && t <= 0) {
|
||||
randomLook();
|
||||
t = randomLookDelay;
|
||||
}
|
||||
t--;
|
||||
if (lookingAt != null && canSeeTarget()) {
|
||||
Util.faceEntity(npc.getEntity(), lookingAt);
|
||||
if (npc.getEntity().getType().name().toLowerCase().contains("shulker")) {
|
||||
NMS.setPeekShulker(npc.getEntity(), 100 - (int) Math
|
||||
.floor(npc.getStoredLocation().distanceSquared(lookingAt.getLocation(PLAYER_LOCATION))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(DataKey key) {
|
||||
key.setDouble("range", range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables random looking - will look at a random {@link Location} every so
|
||||
* often if enabled.
|
||||
*/
|
||||
public void setRandomLook(boolean enableRandomLook) {
|
||||
this.enableRandomLook = enableRandomLook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the delay between random looking in ticks
|
||||
*/
|
||||
public void setRandomLookDelay(int delay) {
|
||||
this.randomLookDelay = delay;
|
||||
}
|
||||
|
||||
public void setRandomLookPitchRange(float min, float max) {
|
||||
this.randomPitchRange = new float[] { min, max };
|
||||
}
|
||||
|
||||
public void setRandomLookYawRange(float min, float max) {
|
||||
this.randomYawRange = new float[] { min, max };
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum range in blocks to look at other Entities
|
||||
*/
|
||||
public void setRange(int range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables realistic looking (using line of sight checks). More
|
||||
* computationally expensive.
|
||||
*/
|
||||
public void setRealisticLooking(boolean realistic) {
|
||||
this.realisticLooking = realistic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean toggle() {
|
||||
enabled = !enabled;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LookClose{" + enabled + "}";
|
||||
}
|
||||
|
||||
private static final Location CACHE_LOCATION = new Location(null, 0, 0, 0);
|
||||
private static final Location CACHE_LOCATION2 = new Location(null, 0, 0, 0);
|
||||
private static final Location NPC_LOCATION = new Location(null, 0, 0, 0);
|
||||
private static final Location PLAYER_LOCATION = new Location(null, 0, 0, 0);
|
||||
package net.citizensnpcs.trait;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.command.CommandConfigurable;
|
||||
import net.citizensnpcs.api.command.CommandContext;
|
||||
import net.citizensnpcs.api.persistence.Persist;
|
||||
import net.citizensnpcs.api.trait.Trait;
|
||||
import net.citizensnpcs.api.trait.TraitName;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.util.NMS;
|
||||
import net.citizensnpcs.util.Util;
|
||||
|
||||
/**
|
||||
* Persists the /npc lookclose metadata
|
||||
*
|
||||
*/
|
||||
@TraitName("lookclose")
|
||||
public class LookClose extends Trait implements Toggleable, CommandConfigurable {
|
||||
@Persist("enabled")
|
||||
private boolean enabled = Setting.DEFAULT_LOOK_CLOSE.asBoolean();
|
||||
@Persist
|
||||
private boolean enableRandomLook = Setting.DEFAULT_RANDOM_LOOK_CLOSE.asBoolean();
|
||||
private Player lookingAt;
|
||||
@Persist
|
||||
private int randomLookDelay = Setting.DEFAULT_RANDOM_LOOK_DELAY.asInt();
|
||||
@Persist
|
||||
private float[] randomPitchRange = { -10, 0 };
|
||||
@Persist
|
||||
private float[] randomYawRange = { 0, 360 };
|
||||
private double range = Setting.DEFAULT_LOOK_CLOSE_RANGE.asDouble();
|
||||
@Persist("realisticlooking")
|
||||
private boolean realisticLooking = Setting.DEFAULT_REALISTIC_LOOKING.asBoolean();
|
||||
private int t;
|
||||
|
||||
public LookClose() {
|
||||
super("lookclose");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the target can be seen. Will use realistic line of sight if
|
||||
* {@link #setRealisticLooking(boolean)} is true.
|
||||
*/
|
||||
public boolean canSeeTarget() {
|
||||
return realisticLooking && npc.getEntity() instanceof LivingEntity
|
||||
? ((LivingEntity) npc.getEntity()).hasLineOfSight(lookingAt)
|
||||
: lookingAt != null && lookingAt.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(CommandContext args) {
|
||||
range = args.getFlagDouble("range", args.getFlagDouble("r", range));
|
||||
realisticLooking = args.hasFlag('r');
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a new look-close target
|
||||
*/
|
||||
public void findNewTarget() {
|
||||
List<Player> nearby = new ArrayList<>();
|
||||
for (Entity entity : npc.getEntity().getNearbyEntities(range, range, range)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player player = (Player) entity;
|
||||
if (CitizensAPI.getNPCRegistry().getNPC(entity) != null
|
||||
|| player.getGameMode() == GameMode.SPECTATOR
|
||||
|| entity.getLocation(CACHE_LOCATION).getWorld() != NPC_LOCATION.getWorld()
|
||||
|| player.hasPotionEffect(PotionEffectType.INVISIBILITY)
|
||||
|| isPluginVanished((Player) entity))
|
||||
continue;
|
||||
nearby.add(player);
|
||||
}
|
||||
|
||||
if (!nearby.isEmpty()) {
|
||||
nearby.sort((o1, o2) -> {
|
||||
Location l1 = o1.getLocation(CACHE_LOCATION);
|
||||
Location l2 = o2.getLocation(CACHE_LOCATION2);
|
||||
if (!NPC_LOCATION.getWorld().equals(l1.getWorld()) || !NPC_LOCATION.getWorld().equals(l2.getWorld())) {
|
||||
return -1;
|
||||
}
|
||||
return Double.compare(l1.distanceSquared(NPC_LOCATION), l2.distanceSquared(NPC_LOCATION));
|
||||
});
|
||||
|
||||
|
||||
lookingAt = nearby.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasInvalidTarget() {
|
||||
if (lookingAt == null)
|
||||
return true;
|
||||
if (!lookingAt.isOnline() || lookingAt.getWorld() != npc.getEntity().getWorld()
|
||||
|| lookingAt.getLocation(PLAYER_LOCATION).distanceSquared(NPC_LOCATION) > range) {
|
||||
lookingAt = null;
|
||||
}
|
||||
return lookingAt == null;
|
||||
}
|
||||
|
||||
private boolean isPluginVanished(Player player) {
|
||||
for (MetadataValue meta : player.getMetadata("vanished")) {
|
||||
if (meta.asBoolean()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(DataKey key) {
|
||||
range = key.getDouble("range");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables the trait
|
||||
*/
|
||||
public void lookClose(boolean lookClose) {
|
||||
enabled = lookClose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDespawn() {
|
||||
lookingAt = null;
|
||||
}
|
||||
|
||||
private void randomLook() {
|
||||
Random rand = new Random();
|
||||
float pitch = rand.doubles(randomPitchRange[0], randomPitchRange[1]).iterator().next().floatValue(),
|
||||
yaw = rand.doubles(randomYawRange[0], randomYawRange[1]).iterator().next().floatValue();
|
||||
Util.assumePose(npc.getEntity(), yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!enabled || !npc.isSpawned()) {
|
||||
return;
|
||||
}
|
||||
if (npc.getNavigator().isNavigating() && Setting.DISABLE_LOOKCLOSE_WHILE_NAVIGATING.asBoolean()) {
|
||||
return;
|
||||
}
|
||||
// TODO: remove in a later version, defaults weren't saving properly
|
||||
if (randomPitchRange == null || randomPitchRange.length != 2) {
|
||||
randomPitchRange = new float[] { -10, 0 };
|
||||
}
|
||||
if (randomYawRange == null || randomYawRange.length != 2) {
|
||||
randomYawRange = new float[] { 0, 360 };
|
||||
}
|
||||
npc.getEntity().getLocation(NPC_LOCATION);
|
||||
if (hasInvalidTarget()) {
|
||||
findNewTarget();
|
||||
}
|
||||
if (npc.getNavigator().isNavigating()) {
|
||||
npc.getNavigator().setPaused(lookingAt != null);
|
||||
} else if (lookingAt == null && enableRandomLook && t <= 0) {
|
||||
randomLook();
|
||||
t = randomLookDelay;
|
||||
}
|
||||
t--;
|
||||
if (lookingAt != null && canSeeTarget()) {
|
||||
Util.faceEntity(npc.getEntity(), lookingAt);
|
||||
if (npc.getEntity().getType().name().toLowerCase().contains("shulker")) {
|
||||
NMS.setPeekShulker(npc.getEntity(), 100 - (int) Math
|
||||
.floor(npc.getStoredLocation().distanceSquared(lookingAt.getLocation(PLAYER_LOCATION))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(DataKey key) {
|
||||
key.setDouble("range", range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables random looking - will look at a random {@link Location} every so
|
||||
* often if enabled.
|
||||
*/
|
||||
public void setRandomLook(boolean enableRandomLook) {
|
||||
this.enableRandomLook = enableRandomLook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the delay between random looking in ticks
|
||||
*/
|
||||
public void setRandomLookDelay(int delay) {
|
||||
this.randomLookDelay = delay;
|
||||
}
|
||||
|
||||
public void setRandomLookPitchRange(float min, float max) {
|
||||
this.randomPitchRange = new float[] { min, max };
|
||||
}
|
||||
|
||||
public void setRandomLookYawRange(float min, float max) {
|
||||
this.randomYawRange = new float[] { min, max };
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum range in blocks to look at other Entities
|
||||
*/
|
||||
public void setRange(int range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables realistic looking (using line of sight checks). More
|
||||
* computationally expensive.
|
||||
*/
|
||||
public void setRealisticLooking(boolean realistic) {
|
||||
this.realisticLooking = realistic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean toggle() {
|
||||
enabled = !enabled;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LookClose{" + enabled + "}";
|
||||
}
|
||||
|
||||
private static final Location CACHE_LOCATION = new Location(null, 0, 0, 0);
|
||||
private static final Location CACHE_LOCATION2 = new Location(null, 0, 0, 0);
|
||||
private static final Location NPC_LOCATION = new Location(null, 0, 0, 0);
|
||||
private static final Location PLAYER_LOCATION = new Location(null, 0, 0, 0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user