mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-11-28 05:35:45 +01:00
CommandConfigurable interface, range/realistic looking settings added to LookClose and Text
This commit is contained in:
parent
461d102107
commit
288bcf5e9f
@ -52,9 +52,12 @@ public class Settings {
|
||||
DATABASE_USERNAME("storage.database.username", ""),
|
||||
DEBUG_MODE("general.debug-mode", false),
|
||||
DEFAULT_LOOK_CLOSE("npc.default.look-close", false),
|
||||
DEFAULT_LOOK_CLOSE_RANGE("npc.default.look-close.range", 5),
|
||||
DEFAULT_PATHFINDING_RANGE("npc.pathing.default-pathfinding-range", 25F),
|
||||
DEFAULT_RANDOM_TALKER("npc.default.random-talker", true),
|
||||
DEFAULT_REALISTIC_LOOKING("npc.default.realistic-looking", false),
|
||||
DEFAULT_TALK_CLOSE("npc.default.talk-close", false),
|
||||
DEFAULT_TALK_CLOSE_RANGE("npc.default.talk-close.range", 5),
|
||||
DEFAULT_TEXT("npc.default.text.0", "Hi, I'm <npc>!") {
|
||||
@Override
|
||||
public void loadFromKey(DataKey root) {
|
||||
|
@ -0,0 +1,5 @@
|
||||
package net.citizensnpcs.command;
|
||||
|
||||
public interface CommandConfigurable {
|
||||
void configure(CommandContext args);
|
||||
}
|
@ -135,9 +135,11 @@ public class CommandManager {
|
||||
if (cmd.max() != -1 && context.argsLength() > cmd.max())
|
||||
throw new CommandUsageException("Too many arguments.", getUsage(args, cmd));
|
||||
|
||||
for (char flag : context.getFlags())
|
||||
if (cmd.flags().indexOf(String.valueOf(flag)) == -1)
|
||||
throw new CommandUsageException("Unknown flag: " + flag, getUsage(args, cmd));
|
||||
if (!context.getFlags().contains('*')) {
|
||||
for (char flag : context.getFlags())
|
||||
if (cmd.flags().indexOf(String.valueOf(flag)) == -1)
|
||||
throw new CommandUsageException("Unknown flag: " + flag, getUsage(args, cmd));
|
||||
}
|
||||
|
||||
methodArgs[0] = context;
|
||||
Object instance = instances.get(method);
|
||||
|
@ -13,6 +13,7 @@ import net.citizensnpcs.api.trait.trait.MobType;
|
||||
import net.citizensnpcs.api.trait.trait.Owner;
|
||||
import net.citizensnpcs.api.trait.trait.Spawned;
|
||||
import net.citizensnpcs.command.Command;
|
||||
import net.citizensnpcs.command.CommandConfigurable;
|
||||
import net.citizensnpcs.command.CommandContext;
|
||||
import net.citizensnpcs.command.Requirements;
|
||||
import net.citizensnpcs.command.exception.CommandException;
|
||||
@ -557,4 +558,27 @@ public class NPCCommands {
|
||||
Messaging.sendF(sender, ChatColor.GREEN + "Trait %s added successfully.",
|
||||
StringHelper.wrap(traitName));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "traitc|tc [trait name] [flags]",
|
||||
desc = "Configures a trait",
|
||||
modifiers = { "traitc", "tc" },
|
||||
min = 2,
|
||||
flags = "*",
|
||||
permission = "npc.trait-configure")
|
||||
public void traitConfigure(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
||||
String traitName = args.getString(1);
|
||||
if (!sender.hasPermission("citizens.npc.trait-configure." + traitName))
|
||||
throw new NoPermissionsException();
|
||||
Class<? extends Trait> clazz = CitizensAPI.getTraitFactory().getTraitClass(args.getString(1));
|
||||
if (clazz == null)
|
||||
throw new CommandException("Trait not found.");
|
||||
if (!clazz.isAssignableFrom(CommandConfigurable.class))
|
||||
throw new CommandException("That trait is not configurable");
|
||||
if (!npc.hasTrait(clazz))
|
||||
throw new CommandException("The NPC doesn't have that trait.");
|
||||
CommandConfigurable trait = (CommandConfigurable) npc.getTrait(clazz);
|
||||
trait.configure(args);
|
||||
}
|
||||
}
|
@ -5,63 +5,58 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||
import net.citizensnpcs.api.trait.Trait;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.minecraft.server.EntityLiving;
|
||||
import net.citizensnpcs.command.CommandConfigurable;
|
||||
import net.citizensnpcs.command.CommandContext;
|
||||
import net.citizensnpcs.util.Util;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LookClose extends Trait implements Toggleable {
|
||||
public class LookClose extends Trait implements Toggleable, CommandConfigurable {
|
||||
private boolean enabled = Setting.DEFAULT_LOOK_CLOSE.asBoolean();
|
||||
private Player lookingAt;
|
||||
private double range = Setting.DEFAULT_LOOK_CLOSE_RANGE.asDouble();
|
||||
private boolean realisticLooking = Setting.DEFAULT_REALISTIC_LOOKING.asBoolean();
|
||||
|
||||
public LookClose() {
|
||||
super("lookclose");
|
||||
}
|
||||
|
||||
private void faceEntity(Entity from, Entity at) {
|
||||
if (from.getWorld() != at.getWorld())
|
||||
return;
|
||||
Location loc = from.getLocation();
|
||||
private boolean canSeeTarget() {
|
||||
return realisticLooking ? Util.rayTrace(npc.getBukkitEntity(), lookingAt) : true;
|
||||
}
|
||||
|
||||
double xDiff = at.getLocation().getX() - loc.getX();
|
||||
double yDiff = at.getLocation().getY() - loc.getY();
|
||||
double zDiff = at.getLocation().getZ() - loc.getZ();
|
||||
|
||||
double distanceXZ = Math.sqrt(xDiff * xDiff + zDiff * zDiff);
|
||||
double distanceY = Math.sqrt(distanceXZ * distanceXZ + yDiff * yDiff);
|
||||
|
||||
double yaw = (Math.acos(xDiff / distanceXZ) * 180 / Math.PI);
|
||||
double pitch = (Math.acos(yDiff / distanceY) * 180 / Math.PI) - 90;
|
||||
if (zDiff < 0.0) {
|
||||
yaw = yaw + (Math.abs(180 - yaw) * 2);
|
||||
}
|
||||
|
||||
EntityLiving handle = ((CraftLivingEntity) from).getHandle();
|
||||
handle.yaw = (float) yaw - 90;
|
||||
handle.pitch = (float) pitch;
|
||||
handle.as = handle.yaw;
|
||||
@Override
|
||||
public void configure(CommandContext args) {
|
||||
range = args.getFlagDouble("range", range);
|
||||
range = args.getFlagDouble("r", range);
|
||||
realisticLooking = args.hasFlag('r');
|
||||
}
|
||||
|
||||
private void findNewTarget() {
|
||||
List<Entity> nearby = npc.getBukkitEntity().getNearbyEntities(2.5, 5, 2.5);
|
||||
List<Entity> nearby = npc.getBukkitEntity().getNearbyEntities(range / 2, range, range / 2);
|
||||
final Location npcLocation = npc.getBukkitEntity().getLocation();
|
||||
Collections.sort(nearby, new Comparator<Entity>() {
|
||||
@Override
|
||||
public int compare(Entity o1, Entity o2) {
|
||||
double d1 = o1.getLocation().distanceSquared(npc.getBukkitEntity().getLocation());
|
||||
double d2 = o2.getLocation().distanceSquared(npc.getBukkitEntity().getLocation());
|
||||
double d1 = o1.getLocation().distanceSquared(npcLocation);
|
||||
double d2 = o2.getLocation().distanceSquared(npcLocation);
|
||||
return Double.compare(d1, d2);
|
||||
}
|
||||
});
|
||||
for (Entity entity : nearby) {
|
||||
if (entity instanceof Player) {
|
||||
lookingAt = (Player) entity;
|
||||
return;
|
||||
}
|
||||
if (entity.getType() != EntityType.PLAYER)
|
||||
continue;
|
||||
if (CitizensAPI.getNPCRegistry().getNPC(entity) != null)
|
||||
continue;
|
||||
lookingAt = (Player) entity;
|
||||
return;
|
||||
}
|
||||
lookingAt = null;
|
||||
}
|
||||
@ -70,33 +65,34 @@ public class LookClose extends Trait implements Toggleable {
|
||||
if (lookingAt == null)
|
||||
return true;
|
||||
if (!lookingAt.isOnline() || lookingAt.getWorld() != npc.getBukkitEntity().getWorld()
|
||||
|| lookingAt.getLocation().distanceSquared(npc.getBukkitEntity().getLocation()) > 5) {
|
||||
|| lookingAt.getLocation().distanceSquared(npc.getBukkitEntity().getLocation()) > range) {
|
||||
lookingAt = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return lookingAt == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(DataKey key) throws NPCLoadException {
|
||||
enabled = key.getBoolean("");
|
||||
range = key.getDouble("range", range);
|
||||
realisticLooking = key.getBoolean("realistic-looking", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!enabled || npc.getNavigator().isNavigating())
|
||||
return;
|
||||
if (hasInvalidTarget()) {
|
||||
if (hasInvalidTarget())
|
||||
findNewTarget();
|
||||
}
|
||||
if (lookingAt != null) {
|
||||
faceEntity(npc.getBukkitEntity(), lookingAt);
|
||||
}
|
||||
if (lookingAt != null && canSeeTarget())
|
||||
Util.faceEntity(npc.getBukkitEntity(), lookingAt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(DataKey key) {
|
||||
key.setBoolean("", enabled);
|
||||
key.setDouble("range", range);
|
||||
key.setBoolean("realistic-looking", realisticLooking);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,6 +3,7 @@ package net.citizensnpcs.trait.text;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
import net.citizensnpcs.util.StringHelper;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.conversations.ConversationContext;
|
||||
import org.bukkit.conversations.Prompt;
|
||||
import org.bukkit.conversations.StringPrompt;
|
||||
@ -24,10 +25,14 @@ public class StartPrompt extends StringPrompt {
|
||||
else if (input.equalsIgnoreCase("remove"))
|
||||
return new TextRemovePrompt(text);
|
||||
else if (input.equalsIgnoreCase("random"))
|
||||
Messaging.send((Player) context.getForWhom(), "<e>Random talker <a>set to <e>" + text.toggleRandomTalker()
|
||||
+ "<a>.");
|
||||
Messaging.send((Player) context.getForWhom(),
|
||||
"<e>Random talker <a>set to <e>" + text.toggleRandomTalker() + "<a>.");
|
||||
else if (input.equalsIgnoreCase("realistic looking"))
|
||||
Messaging.send((CommandSender) context.getForWhom(),
|
||||
"<e>Realistic looking <a>set to <e>" + text.toggleRealisticLooking() + "<a>.");
|
||||
else if (input.equalsIgnoreCase("close"))
|
||||
Messaging.send((Player) context.getForWhom(), "<e>Close talker <a>set to <e>" + text.toggle() + "<a>.");
|
||||
Messaging.send((Player) context.getForWhom(), "<e>Close talker <a>set to <e>" + text.toggle()
|
||||
+ "<a>.");
|
||||
else
|
||||
Messaging.sendError((Player) context.getForWhom(), "Invalid edit type.");
|
||||
|
||||
|
@ -37,6 +37,8 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
|
||||
private int currentIndex;
|
||||
private final Plugin plugin;
|
||||
private boolean randomTalker = Setting.DEFAULT_RANDOM_TALKER.asBoolean();
|
||||
private double range = Setting.DEFAULT_TALK_CLOSE_RANGE.asDouble();
|
||||
private boolean realisticLooker = Setting.DEFAULT_REALISTIC_LOOKING.asBoolean();
|
||||
private boolean talkClose = Setting.DEFAULT_TALK_CLOSE.asBoolean();
|
||||
private final List<String> text = new ArrayList<String>();
|
||||
|
||||
@ -59,9 +61,9 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
|
||||
}
|
||||
|
||||
public Editor getEditor(final Player player) {
|
||||
final Conversation conversation = new ConversationFactory(plugin).addConversationAbandonedListener(this)
|
||||
.withLocalEcho(false).withEscapeSequence("/npc text").withModality(false)
|
||||
.withFirstPrompt(new StartPrompt(this)).buildConversation(player);
|
||||
final Conversation conversation = new ConversationFactory(plugin)
|
||||
.addConversationAbandonedListener(this).withLocalEcho(false).withEscapeSequence("/npc text")
|
||||
.withModality(false).withFirstPrompt(new StartPrompt(this)).buildConversation(player);
|
||||
return new Editor() {
|
||||
|
||||
@Override
|
||||
@ -89,10 +91,10 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
|
||||
if (text.isEmpty())
|
||||
populateDefaultText();
|
||||
|
||||
if (key.keyExists("talk-close"))
|
||||
talkClose = key.getBoolean("talk-close");
|
||||
if (key.keyExists("random-talker"))
|
||||
randomTalker = key.getBoolean("random-talker");
|
||||
talkClose = key.getBoolean("talk-close", talkClose);
|
||||
realisticLooker = key.getBoolean("realistic-looking", realisticLooker);
|
||||
randomTalker = key.getBoolean("random-talker", randomTalker);
|
||||
range = key.getDouble("range", range);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@ -147,6 +149,8 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
|
||||
public void save(DataKey key) {
|
||||
key.setBoolean("talk-close", talkClose);
|
||||
key.setBoolean("random-talker", randomTalker);
|
||||
key.setBoolean("realistic-looking", realisticLooker);
|
||||
key.setDouble("range", range);
|
||||
for (int i = 0; i < text.size(); i++)
|
||||
key.setString(String.valueOf(i), text.get(i));
|
||||
}
|
||||
@ -183,13 +187,15 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
|
||||
|
||||
@Override
|
||||
public boolean toggle() {
|
||||
talkClose = !talkClose;
|
||||
return talkClose;
|
||||
return (talkClose = !talkClose);
|
||||
}
|
||||
|
||||
public boolean toggleRandomTalker() {
|
||||
randomTalker = !randomTalker;
|
||||
return randomTalker;
|
||||
return (randomTalker = !randomTalker);
|
||||
}
|
||||
|
||||
public boolean toggleRealisticLooking() {
|
||||
return (realisticLooker = !realisticLooker);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,6 +37,11 @@ public class WanderingWaypointProvider implements WaypointProvider, Iterable<Loc
|
||||
return currentGoal.isPaused();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Location> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(DataKey key) {
|
||||
}
|
||||
@ -59,9 +64,4 @@ public class WanderingWaypointProvider implements WaypointProvider, Iterable<Loc
|
||||
public void setPaused(boolean paused) {
|
||||
currentGoal.setPaused(paused);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Location> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.event.NPCCollisionEvent;
|
||||
import net.citizensnpcs.api.event.NPCPushEvent;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.minecraft.server.EntityLiving;
|
||||
import net.minecraft.server.Packet;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
@ -11,8 +12,11 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@ -34,6 +38,30 @@ public class Util {
|
||||
return event;
|
||||
}
|
||||
|
||||
public static void faceEntity(Entity from, Entity at) {
|
||||
if (from.getWorld() != at.getWorld())
|
||||
return;
|
||||
Location loc = from.getLocation();
|
||||
|
||||
double xDiff = at.getLocation().getX() - loc.getX();
|
||||
double yDiff = at.getLocation().getY() - loc.getY();
|
||||
double zDiff = at.getLocation().getZ() - loc.getZ();
|
||||
|
||||
double distanceXZ = Math.sqrt(xDiff * xDiff + zDiff * zDiff);
|
||||
double distanceY = Math.sqrt(distanceXZ * distanceXZ + yDiff * yDiff);
|
||||
|
||||
double yaw = (Math.acos(xDiff / distanceXZ) * 180 / Math.PI);
|
||||
double pitch = (Math.acos(yDiff / distanceY) * 180 / Math.PI) - 90;
|
||||
if (zDiff < 0.0) {
|
||||
yaw = yaw + (Math.abs(180 - yaw) * 2);
|
||||
}
|
||||
|
||||
EntityLiving handle = ((CraftLivingEntity) from).getHandle();
|
||||
handle.yaw = (float) yaw - 90;
|
||||
handle.pitch = (float) pitch;
|
||||
handle.as = handle.yaw;
|
||||
}
|
||||
|
||||
public static boolean isSettingFulfilled(Player player, Setting setting) {
|
||||
String parts = setting.asString();
|
||||
if (parts.contains("*"))
|
||||
@ -59,6 +87,12 @@ public class Util {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean rayTrace(LivingEntity entity, LivingEntity entity2) {
|
||||
EntityLiving from = ((CraftLivingEntity) entity).getHandle();
|
||||
EntityLiving to = ((CraftLivingEntity) entity2).getHandle();
|
||||
return from.l(to);
|
||||
}
|
||||
|
||||
public static void sendPacketNearby(Location location, Packet packet, double radius) {
|
||||
radius *= radius;
|
||||
final World world = location.getWorld();
|
||||
|
Loading…
Reference in New Issue
Block a user